Du var en del af vejen dertil ved korrekt at identificere de operationer, du skal udføre. Men selvfølgelig $sort
er ikke en gyldig modifikator for $addToSet
da MongoDB-mantraet er "sæt anses ikke for at være bestilt" :
Det andet problem her, som angivet af fejlen, er, at du ikke kan bruge flere opdateringsoperatører (såsom $addToSet
og $push
) på samme vej til en ejendom på samme tid. Der er faktisk "ingen ordre" til udførelsen af forskellige opdateringsoperatører, så de er ingen garanti for, at $addToSet
forekommer før $push
. Faktisk handler de sandsynligvis parallelt, hvilket er grunden til fejlen, og at dette ikke er tilladt.
Svaret er selvfølgelig "to" opdateringsudsagn. En for $addToSet
og en til at anvende $sort
ved at "skubbe" et tomt array via $each
,
Men da vi virkelig ikke ønsker at "vente" på, at hver opdatering er fuldført, er det, hvad "Bulk" operations API er til for. Så du kan sende begge instruktioner til serveren i én send og få en svar:
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();
Så dette er stadig kun én anmodning til serveren og ét svar. Det er stadig "to" operationer, men overheaden og muligheden for, at nogle tråde griber den midlertidige tilstand af opdateringen er ubetydelig.
Der er et alternativ til denne tilgang, som er at flytte "set detection"-logikken til .find()
del af opdateringssætningen og derefter bare anvende $push
hvor det eller de medlemmer, der skal tilføjes til "sættet", ikke allerede eksisterer:
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();
Selvfølgelig er komplikationen, at hvis du tilføjer "flere" array-elementer her, skal du indpakke disse $not
og $elemMacth
test i en $and
betingelse, og hvis "kun ét" af disse elementer var gyldigt, kunne det ikke tilføjes alene.
Du kan "prøve" den slags handling med "flere" elementer "først", men derefter bør have en "faldback"-udførelse af hvert enkelt array-element med samme logik som ovenfor for at "teste" muligheden for at "skubbe" for hvert enkelt element.
Så $addToSet
gør den anden del let med flere array-indgange. For én indtastning er det ganske enkelt bare at "forespørge" og $push
, for mere end én er det sandsynligvis den kortere vej at bruge det "første" mønster med $addToSet
og $push
et tomt array til at "sortere" resultatet, da anvendelse af det andet mønster alligevel betyder flere opdateringstests.