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

Utilisation de l'agrégation pour trier dans le conditionnel complexe dans Mongodb

Tout d'abord, notez que votre exemple de tri est mal formé :la méthode d'agrégation prend un tableau en entrée, où chaque élément du tableau spécifie une étape dans un pipeline d'agrégation. Notez également que le $elemMatch L'opérateur ne peut pas être utilisé dans le cadre d'une étape $sort.

Une façon de réaliser ce que vous essayez de faire avec votre exemple de tri est d'utiliser $détendez-vous exploitant de pipeline. Le déroulement d'un tableau décollera les éléments du tableau un par un dans des documents séparés. Par exemple, la requête suivante

db.my_collection.aggregate([ {$unwind: "$answers"} ]);

renvoie quelque chose comme ceci :

[
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 0,
            "value" : 3.5
        }
    },
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 1,
            "value" : "hello"
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 0,
            "value" : 0.5
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 1,
            "value" : "world"
        }
    }
]

L'ajout d'une phase $match vous permettra de récupérer uniquement les documents où answers.id est égal à zéro. Enfin, une phase $sort permet de trier par answers.value. Au total, la requête d'agrégation est :

db.my_collection.aggregate([
    {$unwind: "$answers"},
    {$match: {"answers.id": 0}},
    {$sort: {"answers.value": -1}}
]);

Et le résultat :

[
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 0,
            "value" : 3.5
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 0,
            "value" : 0.5
        }
    }
]

D'après ce que vous demandez, il ne semble pas que vous ayez toujours besoin de $unwind ou même du cadre d'agrégation. Si à la place vous vouliez trouver le document avec answers.id égal à 0 et answers.value égal à 3,5, puis changer answers.value à 4, vous pouvez utiliser find avec $elemMatch suivi de db.collection.save() :

doc = db.my_collection.findOne({"answers": {$elemMatch: {"id": 0, "value": 3.5}}});
for (i=0; i<doc.answers.length; i++) {
  if (doc.answers[i].id === 0) {
    doc.answers[i].value = 4;
    db.my_collection.save(doc);
    break;
  }
}