Het proces hier is eigenlijk vrij eenvoudig, het varieert alleen in waar je de elementen in de array wilt "vinden of maken".
Ten eerste, ervan uitgaande dat de elementen voor elke sleutel al aanwezig zijn, dan is het eenvoudige geval om het element op te vragen en bij te werken met de index die wordt geretourneerd via de positional $
operator:
db.collection.update(
{
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
}
{ "$set": { "attrs.$.value": "20" }
)
Dat zal alleen het element wijzigen dat overeenkomt zonder anderen te beïnvloeden.
In het tweede geval waarin "find or create" vereist is en de specifieke sleutel mogelijk niet bestaat, gebruikt u "twee" update-statements. Maar de Bulk Operations API stelt u in staat om dit te doen in een enkel verzoek aan de server met een enkel antwoord:
var bulk = db.collection.initializeOrderedBulkOp();
// Try to update where exists
bulk.find({
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T2" } }
}).updateOne({
"$set": { "attrs.$.value": "30" }
});
// Try to add where does noes not exist
bulk.find({
"_id": docId,
"attrs": { "$not": { "$elemMatch": { "key": "A1", "type": "T2" } } }
}).updateOne({
"$push": { "attrs": { "key": "A1", "type": "T2", "value": "30" } }
});
bulk.execute();
De basislogica is dat eerst de updatepoging wordt gedaan om een element te matchen met de vereiste waarden, net zoals eerder gedaan. De andere voorwaarde test waar het element helemaal niet wordt gevonden door de matchlogica om te keren met $not
.
In het geval dat het array-element niet werd gevonden, is een nieuwe geldig voor toevoeging via $push
.
Ik moet hier echt aan toevoegen dat, aangezien we hier specifiek op zoek zijn naar negatieve overeenkomsten, het altijd een goed idee is om het "document" dat u van plan bent bij te werken, te matchen met een unieke identificatie zoals de _id
sleutel. Hoewel het mogelijk is met "multi"-updates, moet je voorzichtig zijn met wat je doet.
Dus in het geval van het uitvoeren van het "vind of maak"-proces, wordt het element dat niet overeenkomt, correct aan de array toegevoegd, zonder andere elementen te verstoren, ook de vorige update voor een verwachte overeenkomst wordt op dezelfde manier toegepast:
{
"_id" : ObjectId("55b570f339db998cde23369d"),
"attrs" : [
{
"key" : "A1",
"type" : "T1",
"value" : "20"
},
{
"key" : "A2",
"type" : "T2",
"value" : "14"
},
{
"key" : "A1",
"type" : "T2",
"value" : "30"
}
]
}
Dit is een eenvoudig patroon om te volgen, en natuurlijk verwijderen de bulkbewerkingen hier alle overhead door meerdere verzoeken van en naar de server te verzenden en te ontvangen. Dit alles werkt gelukkig zonder te interfereren met andere elementen die al dan niet bestaan.
Afgezien daarvan zijn er de extra voordelen van het bewaren van de gegevens in een array voor eenvoudige query's en analyses, zoals ondersteund door de standaardoperators zonder de noodzaak om terug te keren naar JavaScript-serververwerking om de elementen te doorkruisen.