sql >> Database >  >> NoSQL >> MongoDB

MongoDB:subdocument upsert

Nee er is niet echt een betere oplossing voor, dus wellicht met uitleg.

Stel dat u een document heeft dat de structuur heeft zoals u laat zien:

{ 
  "name": "foo", 
  "bars": [{ 
       "name": "qux", 
       "somefield": 1 
  }] 
}

Als je zo'n update doet

db.foo.update(
    { "name": "foo", "bars.name": "qux" },
    { "$set": { "bars.$.somefield": 2 } },
    { "upsert": true }
)

Dan is alles in orde omdat er een overeenkomend document is gevonden. Maar als u de waarde van "bars.name" wijzigt:

db.foo.update(
    { "name": "foo", "bars.name": "xyz" },
    { "$set": { "bars.$.somefield": 2 } },
    { "upsert": true }
)

Dan krijg je een mislukking. Het enige dat hier echt is veranderd, is dat in MongoDB 2.6 en hoger de fout iets beknopter is:

WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 16836,
        "errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: bars.$.somefield"
    }
})

Dat is in sommige opzichten beter, maar je wilt toch echt niet "upsert". Wat u wilt doen, is het element toevoegen aan de array waar de "naam" momenteel niet bestaat.

Dus wat je echt wilt, is het "resultaat" van de updatepoging zonder de "upsert"-vlag om te zien of er documenten zijn aangetast:

db.foo.update(
    { "name": "foo", "bars.name": "xyz" },
    { "$set": { "bars.$.somefield": 2 } }
)

Toegeven als reactie:

WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })

Dus wanneer de gewijzigde documenten 0 . zijn dan weet je dat je de volgende update wilt uitgeven:

db.foo.update(
    { "name": "foo" },
    { "$push": { "bars": {
        "name": "xyz",
        "somefield": 2
    }}
)

Er is echt geen andere manier om precies te doen wat je wilt. Aangezien de toevoegingen aan de array niet strikt een "set"-type bewerking zijn, kunt u $addToSet niet gebruiken gecombineerd met de "bulk update"-functionaliteit daar, zodat u uw updateverzoeken kunt "cascaderen".

In dit geval lijkt het erop dat u het resultaat moet controleren, of anderszins moet accepteren dat u het hele document leest en moet controleren of u een nieuw array-element in de code wilt bijwerken of invoegen.



  1. Snelste manier om een ​​numpy-array op te slaan in redis

  2. Een checklist voor ontwikkeling en bedrijfsvoering voor MongoDB

  3. Langlopende bewerkingen beheren in MongoDB

  4. Hoe te controleren of een arrayveld een unieke waarde of een andere array in MongoDB bevat?