MongoDB如何仅返回符合过滤条件的嵌套数组文档
问题原因
你当前的查询无法过滤数组内元素的核心原因:
- 查询条件
{'listings.status':'publish'}的作用是筛选至少包含一个publish状态listing的用户文档,不会对listings数组内部的元素做筛选 - 投影规则
{'listings.status':1, _id:0}仅指定返回listings下的status字段,同样不具备数组元素过滤能力,因此只要父文档匹配条件,数组内所有元素(不管是draft还是publish状态)的status字段都会被返回
正确查询方案
根据你使用的MongoDB版本和需求选择对应写法:
方案1:仅返回每个用户第一个匹配的publish状态listing(MongoDB 3.2+ 支持)
使用$elemMatch做投影即可,注意该语法只会返回数组中第一个匹配条件的元素,适合单用户最多只有一个publish listing的场景:
db.properties.find( {'listings.status': 'publish'}, { _id: 0, listings: {$elemMatch: {status: 'publish'}} } )
方案2:返回每个用户下所有publish状态的listing(MongoDB 3.4+ 支持)
如果需要拿到用户下所有符合条件的listing,使用聚合管道的$filter操作符过滤数组元素:
db.properties.aggregate([ // 先过滤掉完全没有publish listing的文档,减少后续计算量 {$match: {'listings.status': 'publish'}}, {$project: { _id: 0, listings: { $filter: { input: '$listings', as: 'singleListing', cond: {$eq: ['$$singleListing.status', 'publish']} } } }} ])
方案3:find直接过滤数组(MongoDB 4.4+ 支持)
4.4及以上版本支持在find的投影参数中直接使用聚合表达式,写法更简洁:
db.properties.find( {'listings.status': 'publish'}, { _id: 0, listings: { $filter: { input: '$listings', cond: {$eq: ['$$this.status', 'publish']} } } } )
预期返回结果
使用支持返回全量匹配元素的方案后,返回结果会完全剔除draft状态的条目,格式如下:
[ { listings: [ { status: 'publish' } ] }, { listings: [ { status: 'publish' } ] }, { listings: [ { status: 'publish' } ] }, { listings: [ { status: 'publish' } ] } ]
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

