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

È possibile utilizzare la proiezione della query sulla stessa raccolta che ha una proiezione $elemMatch?

Sì, ci sono due modi per farlo. Quindi puoi utilizzare il $elemMatch lato proiezione come già hai, con lievi modifiche:

Model.findById(id,
   { "comments": { "$elemMatch": {"created.by": "Jane" } } },
   function(err,doc) {

Oppure aggiungi semplicemente alla parte della query e usa il $ posizionale operatore:

Model.findOne(
    { "_id": id, "comments.created.by": "Jane" },
    { "comments.$": 1 },
    function(err,doc) {

In entrambi i casi è perfettamente valido.

Se desideri qualcosa di un po' più complesso, puoi utilizzare .aggregate() metodo ed è $project operatore invece:

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) {

Quindi il framework di aggregazione può essere utilizzato per molto di più della semplice aggregazione dei risultati. È $project operatore ti offre più flessibilità di quella disponibile per la proiezione usando .find() . Ti consente anche di filtrare e restituire più risultati di array, cosa che non può essere eseguita con la proiezione in .find() .