是否有办法使用db.collection.find()查询子文档中的特定值并查找匹配的文档。例如:
{ {'Joe':{eyecolor:'brown'}, {'Mary':{eyecolor:'blue'}, .... }
我想要回复所有眼睛颜色为蓝色的人的名字。
答案 0 :(得分:3)
您需要指定搜索的值的完整路径:
db.people.find({ "Joe.eyecolor" : "brown" })
您无法切换到人数组而不是现在使用的关联数组样式,因为无法仅返回与条件匹配的数组元素。您可以使用$elemMatch
返回第一次匹配,但这不太可能是您想要的。或者,您仍然可以使用数组,但是您需要在客户端代码(而不是数据库)中进一步过滤数组。
您可能可以使用聚合框架,但它不会有效地使用索引,因为您需要$unwind
整个数组,然后进行过滤,暴力破解。如果包含的数据更复杂,使用AF时的投影需要您手动指定所有字段,这会变得有点麻烦。
为了最有效地执行您正在显示的查询,您不需要使用子文档,而是将人员作为单独的文档放置:
{
name: "Joe",
eyecolor: "brown"
}
然后,你可以做一个简单的搜索,如:
db.people.find({eyecolor: "brown"})
答案 1 :(得分:1)
是和否。您可以查询具有匹配人员的所有文档,但不能直接查询所有人员。换句话说,子文档不是虚拟集合,您将始终返回“父”文档。
您发布的示例带有额外的复杂性,您使用该名称作为字段键,这会阻止您使用点表示法。
一般来说,如果你有很多相似的东西,最好把它们放在一个列表中,例如
{
"_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