sql >> Base de Datos >  >> NoSQL >> MongoDB

mongo agregar a la matriz anidada si la entrada no contiene dos campos que coincidan

Me temo que no es posible con una sola actualización atómica, tendría que hacer un par de operaciones de actualización que satisfagan ambas condiciones.

Divida la lógica de actualización en dos operaciones de actualización distintas, la primera requeriría el uso de posicional $ operador para identificar el elemento en el history matriz que desea y el $set para actualizar los campos existentes. Esta operación sigue la lógica actualizar campos SI el nombre Y la organización coinciden

Ahora, le gustaría usar el findAndModify() para esta operación ya que puede devolver el documento actualizado. Por defecto, el documento devuelto no incluye las modificaciones realizadas en la actualización.

Entonces, armado con este arsenal, puede probar su segunda lógica en la siguiente operación, es decir, actualizar SI esa combinación de "historia.nombre" e "historia.organización" no existe en la matriz . Con esta segunda operación de actualización, deberá usar $push operador para agregar los elementos.

El siguiente ejemplo demuestra el concepto anterior. Inicialmente se supone que tiene la parte de la consulta y el documento que se va a actualizar como objetos separados.

Tomemos, por ejemplo, cuando tenemos documentos que coinciden con la matriz de historial existente, solo realizará una única operación de actualización, pero si los documentos no coinciden, entonces findAndModify() devolverá un valor nulo, use esta lógica en su segunda operación de actualización para enviar el documento a la matriz:

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

Después de esta operación para los documentos que coinciden, la consulta de la colección arrojará el mismo

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

Salida:

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

Ahora considere los documentos que no coincidirán:

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

Consultando esta colección para este documento

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

rendiría

Salida:

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