Byli jste součástí cesty tím, že jste správně identifikovali operace, které musíte udělat. Ale samozřejmě $sort
není platný modifikátor pro $addToSet
protože MongoDB mantra je "sady nejsou považovány za objednané" :
Dalším problémem zde, jak naznačuje chyba, je to, že nemůžete použít více operátorů aktualizace (například $addToSet
a $push
) na stejné cestě k vlastnosti ve stejnou dobu. Ve skutečnosti neexistuje žádný příkaz k provádění různých operátorů aktualizací, takže tito nemají žádnou záruku, že $addToSet
dojde před $push
. Ve skutečnosti pravděpodobně jednají paralelně, což je důvod, proč došlo k chybě a že to není povoleno.
Odpovědí jsou samozřejmě „dvě“ aktualizační prohlášení. Jeden pro $addToSet
a jeden pro použití $sort
"zatlačením" prázdného pole přes $each
,
Ale protože opravdu nechceme „čekat“ na dokončení každé aktualizace, k tomu slouží API pro „hromadné“ operace. Můžete tedy odeslat oba pokyny na server v jednom odeslat a získat jeden odpověď:
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();
Takže to je pořád jen jeden požadavek na server a jedna odpověď. Jsou to stále "dvě" operace, ale režie a možnost, že nějaké vlákno uchopí prozatímní stav uppadte, je zanedbatelné.
Existuje alternativa k tomuto přístupu, která spočívá v přesunutí logiky "set detection" do .find()
část prohlášení o aktualizaci a poté stačí použít $push
kde členové, kteří mají být přidáni do "množiny", již neexistují:
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();
Samozřejmě je zde komplikace, že pokud zde přidáváte „více“ prvků pole, budete muset zabalit tyto $not
a $elemMacth
testy v $and
podmínku, a pokud byl platný „pouze jeden“ z těchto prvků, nelze jej přidat samostatně.
Tento druh operace můžete „nejprve vyzkoušet“ s „více“ položkami, ale pak byste měli mít "záložní" provedení každého jednotlivého prvku pole se stejnou logikou jako výše, abyste "otestovali" možnost "tlačit" pro každý z nich.
Takže $addToSet
usnadňuje tuto druhou část pomocí více položek pole. Pro jeden záznam je docela jednoduché pouze "dotaz" a $push
, pro více než jeden je pravděpodobně kratší cesta k použití "prvního" vzoru s $addToSet
a $push
prázdné pole pro "třídění" výsledku, protože použití druhého vzoru stejně znamená více testů aktualizace.