Je was een deel van de weg daarheen door de operaties die je moest doen correct te identificeren. Maar natuurlijk $sort
is geen geldige wijziging voor $addToSet
aangezien de MongoDB-mantra is "sets worden niet als besteld beschouwd" :
Het andere probleem hier, zoals aangegeven door de fout, is dat u niet meerdere update-operators kunt gebruiken (zoals $addToSet
en $push
) op hetzelfde pad naar een eigenschap op hetzelfde moment. Er is in feite "geen opdracht" voor het uitvoeren van verschillende update-operators, dus het is geen garantie dat de $addToSet
komt voor de $push
. In feite werken ze waarschijnlijk parallel, daarom is de fout en dat dit niet is toegestaan.
Het antwoord is natuurlijk "twee" update-statements. Een voor de $addToSet
en één om de $sort
. toe te passen door een lege array te "duwen" via $each
,
Maar omdat we echt niet willen "wachten" tot elke update is voltooid, is dit waar de API voor "Bulk"-bewerkingen voor is. U kunt dus beide instructies in één . naar de server sturen stuur en ontvang een reactie:
var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({ "name": "Risas" }).update({
"$addToSet": {
"propiedades": { "name": "cola", "cantidad": 1 }
}
});
bulk.find({ "name": "Risas" }).update({
"$push": {
"propiedades": {
"$each": [ ], "$sort": { "cantidad": -1 }
}
}
});
bulk.execute();
Dus dit is eigenlijk nog steeds maar één verzoek aan de server en één antwoord. Het zijn nog steeds "twee" bewerkingen, maar de overhead en de mogelijkheid dat een of andere thread de tussentijdse status van de update grijpt, is te verwaarlozen.
Er is een alternatief voor deze benadering, namelijk het verplaatsen van de "set-detectie"-logica naar de .find()
deel van de update-instructie en pas dan gewoon $push
toe waar de leden die aan de "set" moeten worden toegevoegd nog niet bestaan:
var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({
"name": "Risas",
"propiedades": {
"$not": { "$elemMatch": { "name": "cola", "cantidad": 1 } }
}
}).update({
"$push": {
"propiedades": {
"$each": [{ "name": "cola", "cantidad": 1 }], "$sort": { "cantidad": -1 }
}
}
});
bulk.execute();
Natuurlijk is de complicatie dat als je hier "meerdere" array-elementen toevoegt, je die $not
en $elemMacth
tests in een $and
voorwaarde, en als "slechts één" van die elementen geldig was, kon deze niet alleen worden toegevoegd.
U kunt dat soort bewerking "eerst" met "meerdere" items "proberen", maar dan moet u moeten hebben een "terugval"-uitvoering van elk afzonderlijk array-element met dezelfde logica als hierboven om de mogelijkheid van "duwen" voor elk element te "testen".
Dus $addToSet
maakt dat tweede deel gemakkelijk met meerdere array-items. Voor één item is het vrij eenvoudig om gewoon te "vragen" en $push
, voor meer dan één is het waarschijnlijk het kortere pad om het "eerste" patroon te gebruiken met $addToSet
en $push
een lege array om het resultaat te "sorteren", aangezien het toepassen van het tweede patroon sowieso meerdere updatetests betekent.