> db.test.insert(
{
"seq" : "1",
"a" : [
{
"k1" : "11",
"k2" : "12"
},
{
"k1" : "21",
"k2" : "22"
}
],
"b" : {
"a" : [
{
"k1" : "11",
"k2" : "12"
},
{
"k1" : "21",
"k2" : "22"
}
]
}
}
)
> db.test.find({ "seq" : "1" }, { "a" : { $elemMatch : { "k2" : "22" } }, "a.k2" : 1 }).pretty();
{
"_id" : ObjectId("5407f3c7e40dd5ddb98ab043"),
"a" : [
{
"k2" : "22"
}
]
}
> db.test.find({ "seq" : "1" }, { "b.a" : { $elemMatch : { "k2" : "22" } }, "b.a.k2" : 1 }).pretty();
error: {
"$err" : "Can't canonicalize query: BadValue Cannot use $elemMatch projection on a nested field.",
"code" : 17287
}
请在上面的2.6.3版本中找到测试结果。我们实际上想要得到下面的测试结果,但是,收到了错误查询。
{
"_id" : ObjectId("5407f3c7e40dd5ddb98ab043"),
"b" : {
"a" : [
{
"k2" : "22"
}
]
}
}
我们希望将此结构保留在上面,希望通过One Query获得结果。
因此,请告知我们是否还有其他One Query,我们找不到。如果没有,那么,我们也想知道您是否愿意在将来提供此错误查询的解决方案。否则,我们希望除了$ elemMatch(投影)之外还有其他选择。
答案 0 :(得分:2)
错误说明了一切 - 你不能在2.6中以这种方式使用$elemMatch
。您可以使用简单的聚合管道获得基本上您想要的结果:
> db.test.aggregate([
{ "$match" : { "seq" : "1" } },
{ "$unwind" : "$b.a" },
{ "$match" : { "b.a.k2" : "22" } },
{ "$project" : { "_id" : 1, "b.a.k2" : 1 } }
])
{ "_id" : ObjectId("5409f00ad5a65fc7ef57f67e"), "b" : { "a" : { "k2" : "22" } } }
但我不得不质疑你为什么要寻找这样的结果。您正在使用seq : "1"
搜索文档,然后您希望在内部搜索要返回的数组的特定元素作为结果。这暗示了架构设计问题。也许你想在b.a
和a
数组的每个元素中都有一个文档,并在每个文档中将seq
这些字段非常规化?我不能自信地说出任何话,因为你没有详细说明为什么你需要看到你所要求的结果。
答案 1 :(得分:0)
您向.find()
提供了三个参数,但它只能访问两个。
db.collection.find(criteria, projection)
原始查询
db.test.find({
"seq": "1"
}, {
"a": {
$elemMatch: {
"k2": "22"
}
},
"a.k2": 1
}).pretty();
组合参数1和2会返回正确的结果。
查询1:
db.test.find({
"seq": "1",
"a": {
$elemMatch: {
"k2": "22"
}
}
}, {
"a.k2": 1
}).pretty();
输出:
{
"_id": ObjectId("540cc98e1aaad58cc1b1ebdd"),
"a": [{
"k2": "12"
}, {
"k2": "22"
}]
}
查询2:
db.test.find({
"seq": "1",
"b.a": {
$elemMatch: {
"k2": "22"
}
}
}, {
"b.a.k2": 1
}).pretty();
查询2的输出
{
"_id": ObjectId("540cc98e1aaad58cc1b1ebdd"),
"b": {
"a": [{
"k2": "12"
}, {
"k2": "22"
}]
}
}