MongoDB:嵌入式阵列$ elemMatch(投影)错误问题

时间:2014-09-05 02:16:30

标签: mongodb projection

> 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(投影)之外还有其他选择。

2 个答案:

答案 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.aa数组的每个元素中都有一个文档,并在每个文档中将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"
        }]
    }
}