为何MongoDB嵌套查询不生效而点链式查询正常?
为什么MongoDB嵌套查询用完整对象匹配失效,点语法却正常?
嘿,这个问题其实是MongoDB里嵌入式文档匹配规则的典型“坑”,我来给你讲明白其中的门道:
第一种写法的问题:完全匹配整个嵌入式文档
你写的第一个查询:
db.users.find({ "groups":{ "dateFrom" : { "$lte" : ISODate("2016-12-31T23:00:00Z") } } })
这种写法的逻辑是:要求groups字段的值和你指定的对象完全一致——意思是groups必须是一个只包含dateFrom这一个键,并且值满足$lte条件的对象,多一个键(比如groupId、dateTo)都不行。
如果你的groups是一个数组(这在用户分组场景里很常见),那这种写法只会匹配数组中存在完全等于你指定对象的元素,而显然你的数组元素肯定还有其他字段,所以自然查不到结果。
第二种写法的正确逻辑:匹配嵌入式文档的特定字段
而点链式语法的查询:
db.users.find({ "groups.dateFrom":{ "$lte" : ISODate("2016-12-31T23:00:00Z") } })
这才是MongoDB中查询嵌入式文档(或数组内嵌入式文档)特定字段的正确姿势:
- 它会忽略
groups里的其他字段,只检查dateFrom这个字段是否满足$lte条件; - 如果
groups是数组,MongoDB会自动遍历数组里的每一个元素,只要其中有一个元素的dateFrom符合条件,整个文档就会被匹配返回。
举个直观例子
假设你的用户文档是这样的:
{ "_id": "user123", "groups": [ { "groupId": "admin", "dateFrom": ISODate("2016-06-01T00:00:00Z"), "dateTo": ISODate("2020-01-01T00:00:00Z") }, { "groupId": "editor", "dateFrom": ISODate("2017-01-01T00:00:00Z") } ] }
- 第一种查询会找不到这个文档,因为数组里没有任何一个元素是仅包含
dateFrom且值满足条件的完整对象; - 第二种查询会成功匹配,因为第一个数组元素的
dateFrom符合$lte要求。
总结
{ "groups": { ... } }= 精确匹配整个嵌入式文档/数组元素,要求键值对完全一致,无多余字段;{ "groups.dateFrom": { ... } }= 匹配嵌入式文档(或数组元素)的指定字段,只关注目标字段的条件是否满足。
内容的提问来源于stack exchange,提问作者user2675118
相关产品推荐
相关产品推荐

