MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mongo zum verschachtelten Array hinzufügen, wenn der Eintrag nicht zwei übereinstimmende Felder enthält

Mit einem einzigen atomaren Update ist das leider nicht möglich, Sie müssten ein paar Update-Operationen durchführen, die beide Bedingungen erfüllen.

Brechen Sie die Aktualisierungslogik in zwei unterschiedliche Aktualisierungsvorgänge auf, der erste würde die Verwendung von positionelles $ Betreiber um das Element im history zu identifizieren gewünschten Array und den $set um die vorhandenen Felder zu aktualisieren. Diese Operation folgt der Logik Felder aktualisieren, WENN Name UND Organisation übereinstimmen

Nun möchten Sie den findAndModify() -Methode für diesen Vorgang, da sie das aktualisierte Dokument zurückgeben kann. Standardmäßig enthält das zurückgegebene Dokument nicht die beim Update vorgenommenen Änderungen.

Bewaffnet mit diesem Arsenal können Sie dann Ihre zweite Logik in der nächsten Operation untersuchen, d. h. aktualisieren, WENN diese Kombination aus "history.name" und "history.organisation" nicht im Array vorhanden ist . Bei diesem zweiten Aktualisierungsvorgang müssten Sie dann den $push Operator zum Hinzufügen der Elemente.

Das folgende Beispiel demonstriert das obige Konzept. Zunächst wird davon ausgegangen, dass Sie den Abfrageteil und das zu aktualisierende Dokument als separate Objekte haben.

Wenn wir beispielsweise Dokumente haben, die mit dem vorhandenen Verlaufs-Array übereinstimmen, wird nur ein einziger Aktualisierungsvorgang durchgeführt, aber wenn die Dokumente nicht übereinstimmen, wird der findAndModify() -Methode null zurückgibt, verwenden Sie diese Logik in Ihrem zweiten Aktualisierungsvorgang, um das Dokument in das Array zu verschieben:

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 } }
    );
}

Nach dieser Operation für übereinstimmende Dokumente ergibt die Abfrage der Sammlung dasselbe

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

Ausgabe:

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

Betrachten Sie nun Dokumente, die nicht übereinstimmen:

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 } }
    );
}

Diese Sammlung wird nach diesem Dokument abgefragt

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

würde nachgeben

Ausgabe:

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