简体   繁体   中英

Mongoose Querying SubDocuments

Hello, im trying to query some nested documents at MongoDB. im using Mongoose.. my documents are like

[
{
    "_id": "5a2ca2227c42ad67682731d4",
    "description": "some descrition",
    "photos": [
        {
            "_id": "5a2ca22b7c42ad67682731d5",  
            "approved": false,
            "text":"good"  
        },
        {
            "_id": "5a2ca72b0a1aa173aaae07da",
            "approved": true,
            "text":"bad"
        },
        {
            "_id": "5a2cabf85a41077a2f87d4e3",    
            "approved": false,
            "text":"bad"
        }
    ]
}
]

I Want to find only photos that have the value "good", at text attribute, here is my find code:

ObjectSchema.find({
        'photos': {
            $elemMatch : {
                'text' : 'good'
            }
        }
    },function(err,result){
       console.log(result);
    });

I Wanted only to return the objct with the element with value that match my query, but when one object of this list match, the whole list of photos come with the result, not only who match the text.. How can i query it, and bring only the element who match, in this case, only the element which have "good" in text..

im using nodejs + mongoose

Thank you!

You are using find with only conditions, which will return entire documents. You can also specify a projection with find to include/exclude certain fields from documents. You can use the $elemMatch in the projection as follows:

ObjectSchema.find({
    'photos': {
        $elemMatch : {
            'text' : 'good'
        }
    }
}, {
    'photos': {
        $elemMatch : {
            'text' : 'good'
        }
    }
}, function(err,result){
   console.log(result);
});

But beware that $elemMatch in the projection will only include the first matching array element . That is probably not what you want based on the sample doc. Instead, you can use the Aggregation Framework . You can start with something like the following (untested) and shape the output as you prefer:

ObjectSchema.aggregate(
    {$unwind: "$photos"},
    {$match: {"photos.text": "good"}},
    function(err,result){
        console.log(result);
    }
)

where the $unwind makes a separate document for each element of the array.

To shape the output as you describe in the comment, you need to use a $group aggregation . Try adding the a $group aggregation similar to the following onto the end of pipeline:

{$group: {_id: "$_id", photos: {$push: "$photos"}}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM