MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Verwenden der Aggregation zum Sortieren in komplexen Bedingungen in Mongodb

Beachten Sie zunächst, dass Ihr Sortierbeispiel fehlerhaft ist:Die Aggregatmethode verwendet ein Array als Eingabe, wobei jedes Element im Array eine Stufe in einer Aggregationspipeline angibt. Beachten Sie auch, dass $elemMatch -Operator kann nicht als Teil einer $sort-Phase verwendet werden.

Eine Möglichkeit, das zu erreichen, was Sie mit Ihrem Sortierbeispiel erreichen möchten, besteht darin, $entspannen Pipeline-Betreiber. Beim Abwickeln eines Arrays werden die Array-Elemente einzeln in separate Dokumente abgezogen. Beispielsweise die folgende Abfrage

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

gibt etwa Folgendes zurück:

[
    {
        "_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"
        }
    }
]

Wenn Sie eine $match-Phase hinzufügen, können Sie nur die Dokumente abrufen, bei denen answers.id null ist. Schließlich erlaubt Ihnen eine $sort-Phase, nach answers.value zu sortieren. Insgesamt lautet die Aggregationsabfrage:

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

Und die Ausgabe:

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

Basierend auf Ihrer Frage klingt es nicht so, als würden Sie immer $unwind oder sogar das Aggregationsframework benötigen. Wenn Sie stattdessen das Dokument mit answers.id gleich 0 und answers.value gleich 3,5 finden und dann answers.value auf 4 ändern möchten, können Sie find mit $elemMatch gefolgt von db.collection.save() verwenden:

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