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

mongo aggiungi all'array nidificato se la voce non contiene due campi che corrispondono

Non è possibile con un singolo aggiornamento atomico, temo, dovresti eseguire un paio di operazioni di aggiornamento che soddisfino entrambe le condizioni.

Suddividi la logica di aggiornamento in due distinte operazioni di aggiornamento, la prima richiederebbe l'utilizzo di posizionale $ operatore per identificare l'elemento nella history array desiderato e $set per aggiornare i campi esistenti. Questa operazione segue la logica aggiorna i campi SE il nome E l'organizzazione corrispondono

Ora, vorresti utilizzare il findAndModify() metodo per questa operazione poiché può restituire il documento aggiornato. Per impostazione predefinita, il documento restituito non include le modifiche apportate all'aggiornamento.

Quindi, armato di questo arsenale, puoi quindi sondare la tua seconda logica nella prossima operazione, ad esempio aggiorna SE quella combinazione di "history.name" e "history.organisation" non esiste nell'array . Con questa seconda operazione di aggiornamento, dovresti quindi utilizzare il $push operatore per aggiungere gli elementi.

L'esempio seguente mostra il concetto precedente. Inizialmente presuppone che la parte della query e il documento vengano aggiornati come oggetti separati.

Prendi ad esempio quando abbiamo documenti che corrispondono all'array della cronologia esistente, eseguirà solo una singola operazione di aggiornamento, ma se i documenti non corrispondono, allora findAndModify() il metodo restituirà null, usa questa logica nella tua seconda operazione di aggiornamento per eseguire il push del documento nell'array:

var doc = {
        "name": "Test123",
        "organisation": "Rat"
    }, // document to update. Note: the doc here matches the existing array
    query = { "email": "[email protected]" }; // query document

query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
    "query": query,
    "update": { 
        "$set": { 
            "history.$.name": doc.name,
            "history.$.organisation": doc.organisation
        }
    }
}); // return the document modified, if there's no matched document update = null

if (!update) {
    db.users.update(
        { "email": query.email },
        { "$push": { "history": doc } }
    );
}

Dopo questa operazione per i documenti che corrispondono, interrogare la collezione produrrà lo stesso

db.users.find({ "email": "[email protected]" });

Risultato:

{
    "_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
    "email" : "[email protected]",
    "__v" : 0,
    "history" : [ 
        {
            "name" : "Test123",
            "organisation" : "Rat",
            "field" : 4,
            "another" : 3
        }
    ]
}

Ora considera i documenti che non corrispondono:

var doc = {
        "name": "foo",
        "organisation": "bar"
    }, // document to update. Note: the doc here does not matches the current array
    query = { "email": "[email protected]" }; // query document

query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
    "query": query,
    "update": { 
        "$set": { 
            "history.$.name": doc.name,
            "history.$.organisation": doc.organisation
        }
    }
}); // return the document modified, if there's no matched document update = null

if (!update) {
    db.users.update(
        { "email": query.email },
        { "$push": { "history": doc } }
    );
}

Interrogazione di questa raccolta per questo documento

db.users.find({ "email": "[email protected]" });

cederebbe

Risultato:

{
    "_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
    "email" : "[email protected]",
    "__v" : 0,
    "history" : [ 
        {
            "name" : "Test123",
            "organisation" : "Rat",
            "field" : 4,
            "another" : 3
        }, 
        {
            "name" : "foo",
            "organisation" : "bar"
        }
    ]
}