【问题标题】:MongoDB: Embedded Array $elemMatch(projection) error issueMongoDB:嵌入式数组 $elemMatch(projection) 错误问题
【发布时间】:2014-09-05 02:16:30
【问题描述】:
> 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(projection) 以外的替代方案。

【问题讨论】:

  • 这是什么语言?你用的是什么数据库?请为问题添加适当的标签。

标签: mongodb projection


【解决方案1】:

错误说明了一切——你不能在 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 等字段非规范化到每个文档中?我无法自信地说出任何话,因为您没有详细说明为什么需要看到您所要求的结果。

【讨论】:

    【解决方案2】:

    您向.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"
            }]
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      • 2013-09-18
      • 1970-01-01
      • 2017-10-22
      • 1970-01-01
      相关资源
      最近更新 更多