Mongoose 查询子文档

5

你好,我正在尝试在MongoDB中查询一些嵌套文档。我正在使用Mongoose。我的文档结构如下:

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

我想要找到只有属性文本中值为“good”的照片,这是我的查找代码:

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

我只希望返回与我的查询匹配的元素对象,但是当列表中的一个对象匹配时,整个照片列表都会随结果一起返回,而不仅仅是匹配文本的对象。 在这种情况下,如何查询并仅获取匹配的元素? 即仅包含具有文本中包含“good”的元素。
我使用的是nodejs + mongoose 谢谢!

可能是重复的问题,参考在MongoDB集合中仅检索对象数组中查询的元素 - s7vr
1个回答

7

您正在使用仅有条件的 find,这将返回整个文档。您也可以find 中指定投影以包含/排除文档中的某些字段。您可以在投影中使用 $elemMatch,如下所示:

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

但是要注意投影中的$elemMatch仅包括第一个匹配的数组元素。根据示例文档,这可能不是您想要的。相反,您可以使用聚合框架。您可以从以下内容开始(未经测试),并根据需要进行输出格式:

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

在数组的每个元素上,$unwind会创建一个单独的文档。

为了按照评论中描述的方式输出结果,您需要使用$group聚合。尝试在管道的末尾添加类似以下的$group聚合:

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

可以了!但是每个匹配返回一个文档...有可能让结果像这样[{_id 1, photos[所有匹配项]},{_id 2, photos[所有匹配项]}]吗? - Tobias Guimarães
小修改:聚合的参数应该是一个数组(管道): https://mongoosejs.com/docs/api.html#model_Model.aggregate - René Steetskamp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接