MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

mongo ajouter au tableau imbriqué si l'entrée ne contient pas deux champs qui correspondent

Ce n'est pas possible avec une seule mise à jour atomique, j'ai bien peur que vous deviez effectuer quelques opérations de mise à jour qui satisfont aux deux conditions.

Décomposer la logique de mise à jour en deux opérations de mise à jour distinctes, la première nécessiterait d'utiliser le positionnel $ opérateur pour identifier l'élément dans l'history tableau que vous voulez et le $set pour mettre à jour les champs existants. Cette opération suit la logique mettre à jour les champs SI le nom ET l'organisation correspondent

Maintenant, vous voudriez utiliser le findAndModify() méthode pour cette opération car elle peut renvoyer le document mis à jour. Par défaut, le document retourné n'inclut pas les modifications apportées à la mise à jour.

Ainsi, armé de cet arsenal, vous pouvez ensuite sonder votre deuxième logique lors de l'opération suivante, c'est-à-dire mettre à jour SI cette combinaison de "history.name" et "history.organisation" n'existe pas dans le tableau . Avec cette deuxième opération de mise à jour, vous devrez ensuite utiliser le $push opérateur pour ajouter les éléments.

L'exemple suivant illustre le concept ci-dessus. Il suppose initialement que vous disposez de la partie requête et du document à mettre à jour en tant qu'objets distincts.

Prenons par exemple lorsque nous avons des documents qui correspondent au tableau d'historique existant, il ne fera qu'une seule opération de mise à jour, mais si les documents ne correspondent pas, alors le findAndModify() renverra null, utilisez cette logique dans votre deuxième opération de mise à jour pour envoyer le document au tableau :

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

Après cette opération pour les documents qui correspondent, l'interrogation de la collection donnera le même

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

Sortie :

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

Considérez maintenant les documents qui ne correspondent pas :

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

Interroger cette collection pour ce document

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

donnerait

Sortie :

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