我将使用here
中的示例{
_id: 1,
zipcode: 63109,
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
]
}
{
_id: 2,
zipcode: 63110,
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
]
}
{
_id: 3,
zipcode: 63109,
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
]
}
{
_id: 4,
zipcode: 63109,
students: [
{ name: "barney", school: 102, age: 7 },
]
}
如果我跑
db.schools.find( { zipcode: 63109 },
{ students: { $elemMatch: { school: 102 } } } )
它将给出每个数组的第一个结果。这个命名:
{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] }
{ "_id" : 3 }
{ "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
如何让它返回符合条件的数组的所有对象(而不仅仅是第一个)?这意味着:
{
_id: 1,
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 }
]
}
{ _id: 3 }
{_id: 4, students: [ { name: "barney", school: 102, age: 7 }]}
答案 0 :(得分:18)
为了返回多个子文档,您将需要使用聚合框架。这将返回您正在寻找的所有子文档:
db.zip.aggregate(
{$match: {zipcode: 63109}},
{$unwind: "$students"},
{$match: {"students.school": 102}}
)
你可以做各种事情来获得不同的输出,但这将返回:
{
"result" : [
{
"_id" : 1,
"zipcode" : 63109,
"students" : {
"name" : "john",
"school" : 102,
"age" : 10
}
},
{
"_id" : 1,
"zipcode" : 63109,
"students" : {
"name" : "jess",
"school" : 102,
"age" : 11
}
},
{
"_id" : 4,
"zipcode" : 63109,
"students" : {
"name" : "barney",
"school" : 102,
"age" : 7
}
}
],
"ok" : 1
}
答案 1 :(得分:2)
以前和错误答案:
这应该适用于今天。见https://docs.mongodb.com/v3.2/reference/operator/projection/positional/#array-field-limitations
在查询中使用$elemMatch
查询并在投影中公开子文档时,您应该得到正确的结果,如下所示:
db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } },
{ 'students.$': 1 } )
新答案
使用find()
,现在无法将子文档列表限制为与查询匹配的子文档。请改为aggregate()
或采取以下其中一种方式:
您可以通过在投影中添加array-property来获取匹配文档的所有子文档:
db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } }, { 'students': 1 })
> { "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 }, { "name" : "jess", "school" : 102, "age" : 11 }, { "name" : "jeff", "school" : 108, "age" : 15 } ] }
> { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
或者您可以在子文档中获得与$elemMatch
查询匹配的第一个项目:
db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } }, { 'students.$': 1 })
> { "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] }
> { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
答案 2 :(得分:0)
这在类似过滤的情况下对我有用。现在,我知道这个问题是很多年前问过的,但是对任何想要像我这样的答案的人来说都是这样。这对我有用。多亏了原始答案!
对于此特定问题:
outerparam
是zipcode
,而innerarray.property
是students.school
。
let cursor = db
.collection("somecollection")
.aggregate(
{ $match: { outerparam: outermatch } },
{ $unwind: "$innerarray" },
{ $match: { "innerarray.property": propertymatch } },
{ $project: { "innerarray.$": 1 } });