【问题标题】:Using the db.collection.find query in a sub-document在子文档中使用 db.collection.find 查询
【发布时间】:2013-10-15 11:53:10
【问题描述】:

有没有办法使用 db.collection.find() 来查询子文档中的特定值并找到那些匹配的文档。例如:

{ {“乔”:{眼睛颜色:“棕色”}, {'玛丽':{眼睛颜色:'蓝色'}, …… }

我想返回所有眼睛颜色为蓝色的人的姓名。

【问题讨论】:

  • 这是一个非常糟糕的设计

标签: mongodb find


【解决方案1】:

您需要指定值的完整路径才能进行搜索:

db.people.find({ "Joe.eyecolor" : "brown" })

您不能切换到人员数组来代替您现在使用的关联数组样式,因为无法仅返回匹配条件的数组元素。您可以使用 $elemMatch 返回 first 匹配项,但这可能不是您想要的。或者,您仍然可以使用数组,但您需要在客户端代码(而不是数据库)中进一步过滤数组。

您也许可以使用聚合框架,但它不会有效地使用索引,因为您需要 $unwind 整个数组,然后进行过滤,蛮力。而如果包含的数据比较复杂,使用AF的投影需要手动指定所有字段,就有点麻烦了。

为了最有效地执行您显示的查询,您不需要使用子文档,而是将人员作为单独的文档:

{ 
    name: "Joe",
    eyecolor: "brown" 
}

然后,你可以做一个简单的搜索,比如:

db.people.find({eyecolor: "brown"})

【讨论】:

    【解决方案2】:

    是和不是。您可以查询具有匹配人员的所有文档,但不能直接查询所有人员。换句话说,子文档不是虚拟集合,您将始终返回“父”文档。

    您发布的示例带有额外的复杂性,您将名称用作字段键,这会阻止您使用点表示法。

    一般来说,如果你有很多类似的东西,最好把它们放在一个列表中,例如

    { 
       "_id" : 132,
       "ppl" : [ { "Name" : "John", "eyecolor" : "blue" },
                 { "Name" : "Mary", "eyecolor" : "brown" },
                 ...
               ]
    }
    

    然后,您可以使用聚合框架进行查询:

    db.collection.aggregate([ 
    // only match documents that have a person w/ blue eyes (can use indexing)
    {$match : { "ppl.eyecolor" : "blue" } }, 
    // unwind the array of people
    {$unwind : "$ppl" }, 
    // match only those with blue eyes
    {$match : { "ppl.eyecolor" : "blue" }}, 
    // optional projection to make the result a list of people
    {$project : { Name : "$ppl.Name", EyeColor: "$ppl.eyecolor" }} ]);
    

    这给出了类似的结果

    "result" : [
         {
                 "_id" : 132,
                 "Name" : "John",
                 "EyeColor" : "blue"
         },
         {
                 "_id" : 12,
                 "Name" : "Jimmy",
                 "EyeColor" : "blue"
         },
         {
                 "_id" : 4312,
                 "Name" : "Jimmy",
                 "EyeColor" : "blue"
         },
         {
                 "_id" : 4312,
                 "Name" : "Marc",
                 "EyeColor" : "blue"
         }
    ],
    "ok" : 1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 2013-09-12
      • 2015-04-27
      相关资源
      最近更新 更多