如何查询嵌套对象?

How to query nested objects?

提问人:Edmondo 提问时间:4/15/2013 最后编辑:MachavityEdmondo 更新时间:3/3/2023 访问量:285653

问:

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

db.messages.find( { headers : { From: "[email protected]" } } ).count()
0
db.messages.find( { 'headers.From': "[email protected]" }  ).count()
5

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

mongodb 语法 嵌套 mongodb-query bson

评论


答:

573赞 shx2 4/15/2013 #1

db.messages.find( { headers : { From: "[email protected]" } } )

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


db.messages.find( { 'headers.From': "[email protected]" } )

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


点表示法文档

评论

0赞 trysis 5/1/2014
有没有办法在没有引号的情况下做到这一点 “标题.从“?
0赞 trysis 5/3/2014
我不知道,只是想知道,并认为它有时可能有用。
4赞 Ryan Wheale 5/21/2014
@trysis - 在实践中,我发现在现实世界中声明内联对象(如mongo[ose]文档中的示例,以及大多数示例中的示例)是不够的。我已经养成了创建“条件”和“字段”对象的习惯,我可以在它们上做一些事情,就像在我的业务逻辑中一样,然后在最后运行一个查询:conditions['some.path'] = 'value'find(conditions, fields, callback);
0赞 Rens Tillmann 6/12/2020
如果假设我有一个包含“domain.com”的密钥,这将不起作用:.这种情况是否有任何解决方法(不将 domain.com 更改为其他内容,例如domain_com)?domains.domain.com
2赞 Rens Tillmann 6/12/2020
回答我自己的评论,最好避免在键中完全使用点。在我的解决方案中,我完全放弃了作为键的域,而是创建了一个切片/数组。
30赞 Edmondo 4/15/2013 #2

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

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

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


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

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

评论

10赞 Capaj 11/13/2015
我快疯了。在我看来,这似乎很不一致,因为在查询对象时,它的直接属性可以按任何顺序匹配。
32赞 krishna Prasad 5/5/2019 #3

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

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

> db.messages.find().pretty()
{
    "_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
    "headers" : {
        "From" : "[email protected]"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "[email protected]",
        "To" : "[email protected]"
    }
}
>

那么查询的结果是什么:db.messages.find({headers: {From: "[email protected]"} }).count()

它应该是一个,因为这些对文档的查询等于对象,仅包含其他字段,或者我们应该将整个子文档指定为字段的值。headers{From: "[email protected]"}

所以根据 @Edmondo1984 的回答

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

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

> db.messages.find({headers: {To: "kprasad.ii[email protected]", From: "[email protected]"}  }).count()
0

如果我们要更改第二个文档的子文档的顺序,即与子文档相同怎么办?FromTo

> db.messages.find({headers: {From: "reservat[email protected]", To: "[email protected]"}  }).count()
1

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

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

> db.messages.find( { 'headers.From': "[email protected]" }  ).count()
2

我希望上述示例的这些解释将使某人更清楚地了解使用子文档查找查询

评论

0赞 Nasem 9/9/2022
如果我在 find 方法之后使用 populate 方法会一样吗?' const notes = await Note2.find({“note.title”: “some-title”}).populate(“note”)' 在这里,我正在填充字段注释,在该字段中,我有一个需要用于 find 方法的标题。但它返回一个空数组。为什么会这样?你能看看关于这个问题的问题吗?stackoverflow.com/q/73659370/14835590
-1赞 Adil Ghani 3/3/2023 #4
    //Simple and best solution complete code with example
    
    const mongoose = require("mongoose");
    mongoose
      .connect("mongodb://127.0.0.1:27017/test")
      .then(() => console.log("Connected!"));
    const blogSchema = new mongoose.Schema({
      title: String,
      author: String,
      body: String,
    
      date: { type: Date, default: Date.now },
      hidden: Boolean,
      meta: {
        votes: Number,
        favs: Number,
      },
    });
    const Bloging = mongoose.model("Blog", blogSchema);
    const createDocument = async () => {
      const doc = new Bloging({
        title: "node js",
        author: "adil",
        body: "Monngose Traning",
    
        hidden: true,
        meta: {
          votes: 1000,
          favs: 30,
        },
      });
      const doc2 = new Bloging({
        title: "vue js",
        author: "adil",
        body: "Monngose Traning",
    
        hidden: true,
        meta: {
          votes: 20,
          favs: 80,
        },
      });
      const doc3 = new Bloging({
        title: "React js",
        author: "adil",
        body: "Monngose Traning",
    
        hidden: true,
        meta: {
          votes: 30,
          favs: 60,
        },
      });
      await Bloging.insertMany([doc, doc2, doc3]); // Throws "document must have an _id before saving"
    };
    const getDocument = async () => {
      const result = await Bloging.find({ "meta.favs": { $gt: 60 } });
      console.log(result);
    };
 createDocument();
    getDocument();
   
    
        enter code here
    
    **strong text**

评论

0赞 Community 3/14/2023
正如目前所写的那样,你的答案尚不清楚。请编辑以添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。您可以在帮助中心找到有关如何写出好答案的更多信息。