sql >> Databáze >  >> NoSQL >> MongoDB

Jak mohu $addToSet objekt do pole a také $sort pomocí MongoDB?

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.




  1. mongo docker image po vytvoření nespouští skript

  2. Scrapy a procházení webu pomocí Scrapy a MongoDB

  3. MongoDB:Problém při použití mongoexportu s volbou --query

  4. Přidání nových hodnot do existujícího pole mongo