如何查询嵌套对象?


204

使用嵌套对象表示法查询mongoDB时遇到问题:

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

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

Answers:


419

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

这查询headers 等于的 文档{ From: ... },即不包含其他字段。


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

这只会查看该headers.From字段,而不受包含或缺少的其他字段的影响headers


点符号文档


没有“ headers.From”周围的引号,有没有办法做到这一点?
trysis

我不知道,只是想知道,并且认为它有时可能有用。
trysis

3
@trysis-实际上,我发现声明内联对象(例如mongo [ose]文档中的示例,以及其中的大多数示例)在现实世界中是远远不够的。我养成了创建“条件”和“字段”对象的习惯,可以在这些对象上执行conditions['some.path'] = 'value'业务逻辑中的操作,然后最后运行一个查询:find(conditions, fields, callback);
Ryan Wheale 2014年

如果假设我有一个包含“ domain.com”的密钥,那将不起作用:domains.domain.com。在这种情况下是否有任何解决方法(无需将domain.com更改为其他名称,例如domain_com)?
Rens Tillmann

1
在回答我自己的评论时,最好避免在按键中完全使用圆点。在我的解决方案中,我完全放弃了将域作为键的问题,而是创建了一个切片/数组。
Rens Tillmann

20

以不同的方式在两个查询机制工作,建议在该文档的部分子文档

当字段包含嵌入式文档(即subdocument)时,您可以将整个子文档指定为字段的值,也可以使用点符号“进入” 子文档,以指定子文档中各个字段的值:

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


在下面的示例中,查询将匹配所有文档,其中字段生产者的值是子文档,该子文档仅包含company具有值'ABC123'的字段address和具有值的字段'123 Street'(按确切顺序):

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

8
我快疯了。在我看来,这是非常不一致的,因为查询对象时,它的直接属性可以按任何顺序进行匹配。
卡帕杰

7

由于对带有子文档的查询MongoDB集合存在很多困惑,我认为有必要用示例来解释以上答案:

首先,我仅在集合中插入了两个对象:messageas:

> 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等于object {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

因此,它与指定的子文档完全匹配,包括field order

对于使用点运算符,我认为每一个都非常清楚。让我们看看下面的查询结果:

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

我希望上述示例的这些解释将使人们对使用子文档进行查询更为清晰。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.