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

É possível usar a projeção de consulta na mesma coleção que possui uma projeção $elemMatch?


Sim, existem duas maneiras de fazer isso. Então você pode usar o $elemMatch no lado da projeção como você já tem, com pequenas alterações:
Model.findById(id,
   { "comments": { "$elemMatch": {"created.by": "Jane" } } },
   function(err,doc) {

Ou apenas adicione à parte da consulta e use o $ posicional operador:
Model.findOne(
    { "_id": id, "comments.created.by": "Jane" },
    { "comments.$": 1 },
    function(err,doc) {

Qualquer uma das formas é perfeitamente válida.

Se você queria algo um pouco mais complicado do que isso, você pode usar o .aggregate() e é $project operador em vez disso:
Model.aggregate([
    // Still match the document
    { "$match": "_id": id, "comments.created.by": "Jane" },

    // Unwind the array
    { "$unwind": "$comments" },

    // Only match elements, there can be more than 1
    { "$match": "_id": id, "comments.created.by": "Jane" },

    // Project only what you want
    { "$project": {
        "comments": {
            "body": "$comments.body",
            "by": "$comments.created.by"
        }
    }},

    // Group back each document with the array if you want to
    { "$group": {
        "_id": "$_id",
        "comments": { "$push": "$comments" }
    }}
],
function(err,result) {

Portanto, a estrutura de agregação pode ser usada para muito mais do que simplesmente agregar resultados. É $project operador lhe dá mais flexibilidade do que está disponível para projeção usando .find() . Ele também permite filtrar e retornar vários resultados de array, o que também não pode ser feito com projeção em .find() .