sql >> Database >  >> NoSQL >> MongoDB

mongodb $addToSet naar een niet-arrayveld bij update op upsert

Wat u hier probeert te doen, is een nieuw item alleen aan een array toevoegen waar het item niet bestaat en ook een nieuw document maken waar het niet bestaat. U kiest $addToSet omdat je wilt dat de items uniek zijn, maar in feite wil je dat ze uniek zijn door alleen 'a'.

Dus $addToset zal dat niet doen, en u moet het aanwezige element eerder "testen". Maar het echte probleem hier is dat het niet mogelijk is om dat tegelijkertijd te doen en te "upsert". De logica kan niet werken omdat er een nieuw document wordt gemaakt wanneer het array-element niet is gevonden, in plaats van aan het array-element toe te voegen zoals je wilt.

De huidige bewerkingsfouten zijn ontworpen als $addToSet kan niet worden gebruikt om een ​​array te "maken", maar alleen om leden aan een bestaande array te "toevoegen". Maar zoals al vermeld, heb je andere problemen met het bereiken van de logica.

Wat je hier nodig hebt, is een reeks updatebewerkingen die elk "proberen" om hun verwachte actie uit te voeren. Dit kan alleen met meerdere uitspraken:

// attempt "upsert" where document does not exist
// do not alter the document if this is an update
db.test.update(
    { "name": "abc" },
    { "$setOnInsert": { "config": [{ "a": 1, "b": 2 }] }},
    { "upsert": true }
)

// $push the element where "a": 1 does not exist
db.test.update(
    { "name": "abc", "config.a": { "$ne": 1 } },
    { "$push": { "config": { "a": 1, "b": 2 } }}
)

// $set the element where "a": 1 does exist
db.test.update(
    { "name": "abc", "config.a": 1 },
    { "$set": { "config.$.b": 2 } }
)

Bij een eerste iteratie zal de eerste instructie het document "upsert" en de array met items creëren. De tweede instructie komt niet overeen met het document omdat het "a"-element de opgegeven waarde heeft. Het derde statement komt overeen met het document, maar zal het niet veranderen in een schrijfbewerking omdat de waarden niet zijn veranderd.

Als u nu de invoer wijzigt in "b": 3 je krijgt verschillende reacties maar het gewenste resultaat:

db.test.update(
    { "name": "abc" },
    { "$setOnInsert": { "config": [{ "a": 1, "b": 3 }] }},
    { "upsert": true }
)

db.test.update(
    { "name": "abc", "config.a": { "$ne": 1 } },
    { "$push": { "config": { "a": 1, "b": 3 } }}
)

db.test.update(
    { "name": "abc", "config.a": 1 },
    { "$set": { "config.$.b": 3 } }
)

Dus nu komt het eerste statement overeen met een document met "name": "abc" maar doet niets omdat de enige geldige bewerkingen op "invoegen" zijn. De tweede instructie komt niet overeen omdat "a" overeenkomt met de voorwaarde. De derde verklaring komt overeen met de waarde van "a" en verandert "b" in het overeenkomende element in de gewenste waarde.

Door vervolgens "a" te veranderen in een andere waarde die niet in de array voorkomt, kunnen zowel 1 als 3 niets anders doen dan de tweede instructie voegt een ander lid toe aan de array en houdt de inhoud uniek door hun "a"-sleutels.

Ook het indienen van een verklaring zonder wijzigingen van bestaande gegevens zal natuurlijk resulteren in een reactie waarin staat dat er niets is gewijzigd aan alle accounts.

Zo doe je je operaties. U kunt dit doen met "ordered" Bulk bewerkingen zodat er slechts één verzoek en antwoord van de server is met het geldige antwoord op gewijzigd of aangemaakt.



  1. Hoe de master/slave-status van redis te kennen?

  2. Spring-data mongodb-repository en overerving

  3. native update in Sails with Mongo werkt niet met ObjectId

  4. Hoe documenten opvragen met behulp van het veld _id in het Java-mongodb-stuurprogramma?