MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

mongo adiciona à matriz aninhada se a entrada não contiver dois campos que correspondam


Receio que não seja possível com uma única atualização atômica, você teria que fazer algumas operações de atualização que satisfaçam as duas condições.

Divida a lógica de atualização em duas operações de atualização distintas, a primeira exigiria o uso do posicional $ operador para identificar o elemento no history array desejado e o $set para atualizar os campos existentes. Esta operação segue a lógica atualizar campos SE o nome E a organização corresponderem

Agora, você deve usar o findAndModify() para esta operação, pois pode retornar o documento atualizado. Por padrão, o documento devolvido não inclui as modificações feitas na atualização.

Então, armado com esse arsenal, você pode testar sua segunda lógica na próxima operação, ou seja, atualizar SE essa combinação de "history.name" e "history.organization" não existir no array . Com esta operação de segunda atualização, você precisaria usar o $push operador para adicionar os elementos.

O exemplo a seguir demonstra o conceito acima. Ele inicialmente assume que você tem a parte de consulta e o documento a ser atualizado como objetos separados.

Por exemplo, quando temos documentos que correspondem ao array de histórico existente, ele fará apenas uma única operação de atualização, mas se os documentos não corresponderem, o findAndModify() retornará null, use esta lógica em sua segunda operação de atualização para enviar o documento para a 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 } }
    );
}

Após esta operação para documentos que correspondam, consultar a coleção produzirá o mesmo
db.users.find({ "email": "[email protected]" });

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

Agora considere os documentos que não correspondem:
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 coleção para este documento
db.users.find({ "email": "[email protected]" });

renderia

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