MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Utilizzo dell'aggregazione per l'ordinamento in condizionale complesso in Mongodb

Innanzitutto, nota che il tuo esempio di ordinamento non è corretto:il metodo aggregate accetta una matrice come input, in cui ogni elemento della matrice specifica una fase in una pipeline di aggregazione. Inoltre, tieni presente che $elemMatch l'operatore non può essere utilizzato come parte di una fase di $sort.

Un modo per ottenere ciò che stai cercando di fare con il tuo esempio di ordinamento è utilizzare $rilassati operatore di gasdotto. Lo svolgimento di un array rimuoverà gli elementi dell'array uno per uno in documenti separati. Ad esempio, la seguente query

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

restituisce qualcosa di simile al seguente:

[
    {
        "_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'aggiunta di una fase di $match ti consentirà di acquisire solo i documenti in cui answer.id è zero. Infine, una fase $sort ti consente di ordinare per answer.value. Complessivamente la query di aggregazione è:

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

E l'output:

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

In base a ciò che chiedi, non sembra che avrai sempre bisogno di $unwind o anche del framework di aggregazione. Se invece volevi trovare il documento con answer.id uguale a 0 e answer.value uguale a 3.5, e poi cambiare answer.value a 4 potresti usare find con $elemMatch seguito da 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;
  }
}