2013-10-08 57 views
1

是否有一种方法可以使用db.collection.find()来查询子文档中的特定值并查找匹配的文档。例如:在子文档中使用db.collection.find查询

{{ '乔':{眼睛颜色: '棕'},{ '玛丽':{眼睛颜色: '蓝'}, .... }

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

+0

因此这是一个非常糟糕的设计 –

回答

3

你需要指定的值的完整路径,搜索工作:

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

您不能切换到人数组,而不是你现在正在使用的关联数组的风格,有没有办法只返回符合条件的数组元素。您可以使用$elemMatch返回第一个匹配项,但这不可能是您想要的。或者,您仍然可以使用数组,但是您需要在客户端代码(而不是数据库)中进一步过滤数组。

您可能可以使用Aggregation框架,但它不会有效地使用索引,因为您需要对整个数组使用$unwind,然后执行过滤,强力操作。如果包含的数据更加复杂,那么使用AF时的投影要求您手动指定所有字段,这会变得有点麻烦。

为了最有效地做你的显示查询,你需要不使用子文档,而是把人作为单独的文件:

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

然后,你可以只是做一个简单的搜索像:

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

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

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

一般来说,如果您有许多类似的事情,最好将它们放在一个列表中,例如,

{ 
    "_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