MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Usando agregação para classificar em condicional complexo no Mongodb


Primeiro, observe que seu exemplo de classificação está malformado:o método agregado recebe uma matriz como entrada, onde cada elemento na matriz especifica um estágio em um pipeline de agregação. Além disso, observe que o $elemMatch O operador não pode ser usado como parte de um estágio $sort.

Uma maneira de alcançar o que você está tentando fazer com seu exemplo de classificação é usar o $descontrair operador de dutos. O desenrolar de uma matriz descascará os elementos da matriz um a um em documentos separados. Por exemplo, a seguinte consulta
db.my_collection.aggregate([ {$unwind: "$answers"} ]);

retorna algo como o seguinte:
[
    {
        "_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"
        }
    }
]

Adicionar uma fase $match permitirá que você pegue apenas os documentos em que answers.id é zero. Finalmente, uma fase $sort permite ordenar por respostas.valor. Ao todo, a consulta de agregação é:
db.my_collection.aggregate([
    {$unwind: "$answers"},
    {$match: {"answers.id": 0}},
    {$sort: {"answers.value": -1}}
]);

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

Com base no que você está perguntando, não parece que você sempre precisará de $ unwind ou mesmo da estrutura de agregação. Se, em vez disso, você quiser encontrar o documento com answers.id igual a 0 e answers.value igual a 3,5 e, em seguida, alterar answers.value para 4, você pode usar find com $elemMatch seguido por 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;
  }
}