sql >> Database teknologi >  >> NoSQL >> MongoDB

Hvordan kan jeg $addToSet et objekt til et array og $sortere også ved hjælp af MongoDB?

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.

$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.




  1. Konverter matrix af MongoId-objekter til en matrix af strenge

  2. Redis som unik atom-id-generator - Trådsikker måde til webapp for at undgå racetilstand

  3. Pymongo - ValueError:NaTType understøtter ikke utcoffset ved brug af insert_many

  4. hvordan kan jeg få sessioner til at fungere ved hjælp af redis, express &socket.io?