【问题标题】:How to query nested objects?如何查询嵌套对象?
【发布时间】:2013-04-06 19:52:49
【问题描述】:

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

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

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

【问题讨论】:

    标签: mongodb syntax nested mongodb-query bson


    【解决方案1】:

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

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


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

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


    Dot-notation docs

    【讨论】:

    • 如果没有“headers.From”周围的引号,有什么方法可以做到这一点?
    • 我不知道,只是想知道它有时可能有用。
    • @trysis - 在实践中,我发现声明内联对象(如 mongo[ose] 文档中的示例,以及大多数示例中的示例)在现实世界中是不够的。我已经养成了创建“条件”和“字段”对象的习惯,我可以在这些对象上在我的业务逻辑中执行conditions['some.path'] = 'value' 之类的操作,然后在最后运行一个查询:find(conditions, fields, callback);
    • 如果假设我有一个包含“domain.com”的密钥,这将不起作用:domains.domain.com。这种情况是否有任何解决方法(不将 domain.com 更改为其他内容,例如 domain_com)?
    • 回答我自己的评论,最好避免在键中完全使用点。在我的解决方案中,我完全放弃了作为键的域,而是创建了一个切片/数组。
    【解决方案2】:

    这两种查询机制以不同的方式工作,正如the docs子文档部分所建议的那样:

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

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


    在以下示例中,查询匹配字段 producer 的值是仅包含字段 company 的值为 'ABC123' 和字段 address 的值为 '123 Street' 的子文档的所有文档,准确的顺序:

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

    【讨论】:

    • 我快疯了。在我看来这很不一致,因为在查询对象时,它的直接属性可以按任何顺序匹配。
    【解决方案3】:

    由于使用子文档查询 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"}的文档,只有ie不包含其他字段,或者我们应该将整个子文档指定为一个领域。

    所以根据@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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-02
      • 2013-06-03
      • 2021-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多