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

MongoDB - $set pour mettre à jour ou pousser l'élément Array

En fait, faire ce que vous semblez faire n'est pas une opération singulière, mais je vais passer en revue les parties nécessaires pour le faire ou couvrir d'autres situations possibles.

Ce que vous recherchez est en partie le $ positionnel opérateur. Vous avez besoin d'une partie de votre requête pour "trouver" également l'élément du tableau que vous souhaitez.

db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

Donc le $ représente la position correspondante dans le tableau afin que la partie mise à jour sache quel élément du tableau mettre à jour. Vous pouvez accéder aux champs individuels du document dans le tableau ou simplement spécifier le document entier à mettre à jour à cette position.

db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

Si les champs ne changent pas en fait et que vous voulez juste insérer un nouvel élément de tableau si exactement le même n'existe pas, alors vous pouvez utiliser $addToSet

db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        $addToSet:{ 
            "recentviews": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

Cependant, si vous cherchez simplement à "pousser" vers un tableau par une valeur de clé singulière si cela n'existe pas, vous devez effectuer une manipulation plus manuelle, en voyant d'abord si l'élément du tableau existe, puis en faisant le $push déclaration là où ce n'est pas le cas.

Vous obtenez de l'aide des méthodes de la mangouste pour ce faire en suivant le nombre de documents concernés par la mise à jour :

Product.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    },
    function(err,numAffected) {

        if (numAffected == 0) {
            // Document not updated so you can push onto the array
            Product.update(
                { 
                    "_id": ObjectId("536c55bf9c8fb24c21000095")
                },
                { 
                    "$push": { 
                        "recentviews": {
                            "viewedby": "abc",
                            "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
                        }
                    }
                },
                function(err,numAffected) {

                }
            );
        }            

    }
);

Le seul mot d'avertissement ici est qu'il y a un peu de changement d'implémentation dans les messages writeConcern de MongoDB 2.6 aux versions antérieures. Ne pas être sûr pour l'instant de la manière dont l'API mongoose implémente réellement le retour du numAffected argument dans le rappel, la différence pourrait signifier quelque chose.

Dans les versions précédentes, même si les données que vous avez envoyées dans la mise à jour initiale correspondaient exactement à un élément existant et qu'aucune modification réelle n'était requise, le montant "modifié" serait renvoyé sous la forme 1 même si rien n'a été mis à jour.

À partir de MongoDB 2.6, la réponse de préoccupation d'écriture contient deux parties. Une partie montre le document modifié et l'autre montre la correspondance. Ainsi, alors que la correspondance serait renvoyée par la partie de la requête correspondant à un élément existant, le nombre réel de documents modifiés reviendrait sous la forme 0 si en fait aucun changement n'était nécessaire.

Donc, selon la façon dont le numéro de retour est réellement implémenté dans la mangouste, il peut être plus sûr d'utiliser le $addToSet opérateur sur cette mise à jour interne pour s'assurer que si la raison de l'absence de documents concernés n'était pas simplement que l'élément exact existait déjà.