MongoDB中点符号与对象查询嵌套字段的差异疑问
为什么这两个MongoDB查询结果不一样?
这是MongoDB查询里非常容易踩的语法误区,我来给你掰扯清楚两者的核心差异:
1. 第一个查询:点符号(Dot Notation)的正确用法
你写的第一个查询:
{ 'since.date': { '$lte': ISODate('2018-07-11T09:00:00.000Z') } }
这里用的是MongoDB官方推荐的点符号来定位嵌套字段。它的作用是:精准定位到文档中since这个子对象下的date字段,然后判断这个字段的实际日期值是否满足$lte的范围条件。不管since对象里还有没有其他字段(比如timezone、source之类的),这个查询都会只关注date字段的取值,所以能正确匹配到你的目标文档。
2. 第二个查询:子文档的完整匹配陷阱
而第二个查询:
{ 'since': { 'date': { '$lte': ISODate('2018-07-11T09:00:00.000Z') } } }
这是在做完整子文档匹配,和点符号的逻辑完全不同:
- MongoDB会把整个
since字段当成一个完整的对象去对比,要求它的结构和内容和你写的查询条件完全一致。 - 也就是说,这个查询是在找那些
since对象里只有date这一个字段,并且date字段的取值是{ '$lte': ISODate('...') }这个对象的文档——但你的目标文档里,date字段的实际值是一个ISODate类型的日期,根本不是带查询操作符的对象;如果since里还有其他字段,那就更不可能匹配了。
举个实际的例子,假设你的目标文档是这样的:
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "since": { "date": ISODate("2018-07-10T08:00:00.000Z"), "source": "user_input" } }
第一个查询会检查since.date的日期是否小于等于指定时间,完美匹配;而第二个查询是在找since等于{ date: { '$lte': ... } }的文档,显然和实际文档的结构、内容完全不搭,自然返回空结果。
总结
- 要查询嵌套字段的取值并使用查询操作符(
$lte、$gte、$eq等),一定要用点符号。 - 子文档完整匹配只适用于你需要精确匹配整个子对象结构和内容的场景,不能用来对嵌套字段做范围或条件查询。
内容的提问来源于stack exchange,提问作者Michal
相关产品推荐
相关产品推荐

