如何查询嵌套对象?

我有一个问题,查询mongoDB与嵌套对象符号:

db.messages.find( { headers : { From: "reservations@marriott.com" } } ).count()
0
db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).count()
5

我看不出我做错了什么。我期望嵌套对象表示法返回与点表示法查询相同的结果。我哪里错了?

254021 次浏览

db.messages.find( { headers : { From: "reservations@marriott.com" } } )

这个函数查询那些headers = { From: ... },即不包含其他字段的文档。


db.messages.find( { 'headers.From': "reservations@marriott.com" } )

这只查看headers.From字段,不受headers中包含或缺失的其他字段的影响。


Dot-notation docs

这两种查询机制以不同的方式工作,如的文档节中的子文档所述:

当字段包含一个嵌入的文档(即子文档)时,你可以指定整个子文档作为字段的值,或者使用点表法“进入”子文档,以指定子文档中各个字段的值:

如果子文档完全匹配指定的子文档(包括字段顺序),则在子文档中匹配相等性选择文档。


在下面的例子中,查询匹配所有的文档,其中字段生产者的值是子文档,只包含值为'ABC123'的字段company和值为'123 Street'的字段address,顺序完全相同:

db.inventory.find( {
producer: {
company: 'ABC123',
address: '123 Street'
}
});

由于有很多关于查询MongoDB集合的子文档的困惑,我认为有必要用例子来解释上面的答案:

首先,我只在集合中插入了两个对象,即:message as:

> db.messages.find().pretty()
{
"_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
"headers" : {
"From" : "reservations@marriott.com"
}
}
{
"_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
"headers" : {
"From" : "reservations@marriott.com",
"To" : "kprasad.iitd@gmail.com"
}
}
>

那么查询的结果是什么:db.messages.find({headers: {From: "reservations@marriott.com"} }).count()

它应该是一个,因为这些文档的查询中headers等于对象{From: "reservations@marriott.com"},即不包含其他字段,或者我们应该将整个子文档指定为字段的值。

所以根据@Edmondo1984的回答

如果子文档匹配完全指定的子文档,包括字段顺序,则选择文档。

从上面的语句,下面的查询结果应该是什么?

> db.messages.find({headers: {To: "kprasad.iitd@gmail.com", From: "reservations@marriott.com"}  }).count()
0

如果我们将改变FromTo的顺序,即与第二个文档的子文档相同,会怎样?

> db.messages.find({headers: {From: "reservations@marriott.com", To: "kprasad.iitd@gmail.com"}  }).count()
1

因此,它匹配完全指定的子文档,包括字段顺序

对于点运算符的使用,我想大家都很清楚了。让我们看看下面查询的结果:

> db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).count()
2

我希望以上例子的解释能让人们更清楚地理解用子文档查找查询