Skip to content Skip to sidebar Skip to footer

Is It Possible To Use Query Projection On The Same Collection That Has A $elemmatch Projection?

I understand that you can limit the items in a subcollection array using $elemMatch as a projection. When using it as such it returns all fields of the subdocuments that match rega

Solution 1:

Yes there are two ways to do this. So you can either use the $elemMatch on the projection side as you already have, with slight changes:

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

Or just add to the query portion and use the positional $ operator:

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

Either way is perfectly valid.

If you wanted something a little more involved than that, you can use the .aggregate() method and it's $project operator instead:

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

So the aggregation framework can be used for a lot more than simply aggregating results. It's $project operator gives you more flexibility than is available to projection using .find(). It also allows you to filter and return multiple array results, which is also something that cannot be done with projection in .find().

Post a Comment for "Is It Possible To Use Query Projection On The Same Collection That Has A $elemmatch Projection?"