Créer une unique compound index sur les deux champs
db.collection.createIndex({ "field1": 1, "field2": 1 }, { "unique": true })
utilisation le insertMany()
méthode pour effectuer l'insertion en bloc, mais définissez l'option ordered
sur false car cela garantit que toutes les opérations d'écriture sont tentées, même en cas d'erreurs. les opérations commandées arrêtent après une erreur, alors que les opérations désordonnées continuent de traiter les opérations d'écriture restant dans la file d'attente:
var queryArray = [
{ "field1": "foo", "field2": "xyz" },
{ "field1": "bar", "field2": "lmn" }
];
try { db.collection.insertMany(queryArray, { "ordered": false }); }
catch (e) { print (e); }
Ceci affichera un document
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("57443e6fa58e5654f3a6c5ae"),
ObjectId("57443e6fa58e5654f3a6c5af")
]
}
Le document qui en résulte montre les champs reconnus comme vrai si l'opération s'est déroulée avec un problème d'écriture ou une erreur si l'inquiétude d'écriture a été désactivée et un tableau de _id
pour chaque document inséré avec succès. Parce que les documents dans queryArray n'incluaient pas _id
, mongod crée et ajoute le champ _id pour chaque document et lui assigne une valeur ObjectId unique. Et puisque vous avez imposé l'unicité sur les deux champs field1
et field2
, ce qui précède montre la tentative d'écriture car l'opération n'était pas ordonnée et a donc continué à traiter toutes les opérations d'écriture restantes.
Supposons que vous aviez supprimé l'option ordonnée (par défaut, il est défini sur true), alors vous obtenir la sortie suivante de l'opération:
var queryArray = [
{ "field1": "foo", "field2": "xyz" },
{ "field1": "bar", "field2": "lmn" }
];
try { db.collection.insertMany(queryArray); }
catch (e) { print (e); }
Sortie de la console:
{
"name" : "BulkWriteError",
"message" : "write error at item 0 in bulk operation",
"ok" : undefined,
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"getUpsertedIds" : function() {
return bulkResult.upserted;
},
"getUpsertedIdAt" : function (index) {
return bulkResult.upserted[index];
},
"getRawResponse" : function() {
return bulkResult;
},
"hasWriteErrors" : function() {
return bulkResult.writeErrors.length > 0;
},
"getWriteErrorCount" : function() {
return bulkResult.writeErrors.length;
},
"getWriteErrorAt" : function (index) {
if(index < bulkResult.writeErrors.length) {
return bulkResult.writeErrors[index];
}
return null;
},
"getWriteErrors" : function() {
return bulkResult.writeErrors;
},
"hasWriteConcernError" : function() {
return bulkResult.writeConcernErrors.length > 0;
},
"getWriteConcernError" : function() {
if(bulkResult.writeConcernErrors.length == 0) {
return null;
} else if(bulkResult.writeConcernErrors.length == 1) {
// Return the error
return bulkResult.writeConcernErrors[0];
} else {
// Combine the errors
var errmsg = "";
for(var i = 0; i < bulkResult.writeConcernErrors.length; i++) {
var err = bulkResult.writeConcernErrors[i];
errmsg = errmsg + err.errmsg;
// TODO: Something better
if (i != bulkResult.writeConcernErrors.length - 1) {
errmsg = errmsg + " and ";
}
}
return new WriteConcernError({ errmsg : errmsg, code : WRITE_CONCERN_FAILED });
}
},
"tojson" : function (indent, nolint) {
return tojson(bulkResult, indent, nolint);
},
"toString" : function() {
return "BulkWriteError(" + this.tojson() + ")";
},
"shellPrint" : function() {
return this.toString();
},
"hasErrors" : function() {
return this.hasWriteErrors() || this.hasWriteConcernError();
},
"toSingleResult" : function() {
if(singleBatchType == null) throw Error(
"Cannot output single WriteResult from multiple batch result");
return new WriteResult(bulkResult, singleBatchType, writeConcern);
},
"stack" : "BulkWriteError({\n\t\"writeErrors\" : [\n\t\t{\n\t\t\t\"index\" : 0,\n\t\t\t\"code\" : 11000,\n\t\t\t\"errmsg\" : \"E11000 duplicate key error index: test.collection.$field1_1_field2_1 dup key: { : \\\"foo\\\", : \\\"xyz\\\" }\",\n\t\t\t\"op\" : {\n\t\t\t\t\"_id\" : ObjectId(\"574441aea58e5654f3a6c5b6\"),\n\t\t\t\t\"field1\" : \"foo\",\n\t\t\t\t\"field2\" : \"xyz\"\n\t\t\t}\n\t\t}\n\t],\n\t\"writeConcernErrors\" : [ ],\n\t\"nInserted\" : 0,\n\t\"nUpserted\" : 0,\n\t\"nMatched\" : 0,\n\t\"nModified\" : 0,\n\t\"nRemoved\" : 0,\n\t\"upserted\" : [ ]\n})\[email protected]/mongo/shell/bulk_api.js:372:44\nBulkWriteResult/[email protected]/mongo/shell/bulk_api.js:335:16\nBulk/[email protected]/mongo/shell/bulk_api.js:1162:1\[email protected]/mongo/shell/crud_api.js:279:5\[email protected](shell):1:7\n",
"toResult" : function() {
return new BulkWriteResult(bulkResult, singleBatchType, writeConcern);
}
}
en mettant l'accent sur l'erreur d'écriture retourné:
"E11000 duplicate key error index: test.collection.$field1_1_field2_1 dup key: { : \\\"foo\\\", : \\\"xyz\\\" }\"
En dehors de la méthode insertMany()
, vous pouvez également essayer les Bulk()
méthodes de l'API où, en particulier, vous devez appeler la méthode initializeUnorderedBulkOp()
faire un insert en vrac non ordonnée après la création de l'indice composé unique.
Prenons l'exemple suivant pour le cas ci-dessus:
db.collection('collectionName', function(err, collection) {
var bulk = collection.initializeUnorderedBulkOp();
counter = 0;
querryArray.forEach(function (doc){
bulk.insert(doc);
counter++;
if (counter % 1000 == 0) {
bulk.execute(function(err, result) {
// you could do something with results, check for duplicate errors
bulk = collection.initializeUnorderedBulkOp(); // re-initialise
});
}
});
// Clean-up remaining operations in the queue
if (counter % 1000 != 0) {
bulk.execute(function(err, result) {
// you could do something with results, check for duplicate errors
console.log(result);
});
}
});
une façon de le faire est de créer un index unique sur {filed1: 1, field2: 1} qui assure que le field1 et filed2 sont uniques en insérant les docs – Astro