MongoDB:嵌入式数组 $elemMatch(投影)错误问题

3
> 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"
            }
        ]
    }
}

我们希望保留上述结构,并希望通过一个查询获得结果。因此,请告知是否有其他可用的单一查询。如果没有,我们也想知道您是否愿意在未来提供解决这个错误查询的解决方案。否则,我们希望有除了$elemMatch(projection)之外的其他选择。

2
这是什么编程语言?你正在使用哪个数据库?请为问题添加适当的标签。 - Barmar
2个回答

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 这样的字段去规范化到每个文档中?我不能确定任何事情,因为您没有说明为什么需要看到您所请求的结果。

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"
        }]
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接