【问题标题】:Mongodb nested document where clause returns many subdocumentsMongodb嵌套文档where子句返回许多子文档
【发布时间】:2017-04-02 12:10:04
【问题描述】:

我有一个类似这样的 mongodb 文档:

{
"id": 1,
"title": "This is the title",
"body" : "This is the body",
"comments": [
    {
        "email_address": "mirko.benedetti@somemail.com",
        "name": "Mirko",
        "surname": "Benedetti",
        "language": "it",
        "text": "This is a message",
        "published": "Y",
        "on": "2014-03-22 15:04:04"
    },
    {
        "email_address": "marc.surname@somemail.com",
        "name": "Marc",
        "surname": "Surname",
        "language": "it",
        "text": "Another Message",
        "published": "N",
        "on": "2014-03-23 15:04:05"
    }
  ]
}

我有一个这样的查询:

$this->db->collection->find(array('id' => $id, 'language' => $lang, 'comments.published' => 'Y'),
                        array('comments.name' => 1, 'comments.surname' => 1, 'comments.text' => 1, 'comments.on' => 1, '_id' => 0));

我的问题是运行该查询时,mongodb 返回两个 cmets,这是我不想要的,我只想要带有“已发布”的消息:“Y”。

例如,我尝试运行 'cmets.published' => 'something' 并没有选择任何评论,这是正确的,但如果至少有一个 cmets 有 将“已发布”标志设置为“Y”,同时显示两个 cmets。

欢迎任何帮助。

标签: php mongodb nested-documents


【解决方案1】:

$elemMatch documentation

db.schools.find( { zipcode: "63109" },
                 { students: { $elemMatch: { school: 102 } } } )

【讨论】:

    【解决方案2】:

    在使用 elemMatch 运算符时需要小心。首先它有两种变体。 $elemMatch(projection) & $elemMatch(query)

    elemMatch(projection) 变体似乎有效,因为您拥有的过滤条件仅匹配 cmets 数组中的一个值。

    下面的查询可以正常工作。

    find({'_id' : ObjectId("582f2abf9b549b5a765ab380"), comments: { $elemMatch: { language: "it", published : "Y" }}})
    

    现在考虑当您在 cmets 数组中有超过 1 个匹配值(发布状态为 'Y' 的两个值)时,上述查询将不起作用,只会返回第一个匹配值。

    在这种情况下,您将需要使用$filter,它将根据传递的过滤条件过滤 cmets 数组。

    aggregate([{
        $match: {
            '_id': ObjectId("582f2abf9b549b5a765ab380")
        }
    }, {
        "$project": {
            "comments": {
                "$filter": {
                    "input": "$comments",
                    "as": "result",
                    "cond": {
                        $and: [{
                            $eq: ["$$result.language", "it"]
                        }, {
                            $eq: ["$$result.published", "Y"]
                        }]
                    }
                }
            }
        }
    }, {
        $project: {
            "comments": {
                name: 1,
                surname: 1,
                text: 1,
                on: 1
            }
        }
    }])
    

    【讨论】:

    • 我的问题也是我必须在某个文档(“blog_post”)中选择“cmets”,但我还必须选择正确的文档(blog_post)并且从文档来看不是很直观,有聚合。
    • 您只需要添加匹配阶段,考虑到与我们在查找方法中使用的查询条件相同的查询条件更新答案。希望这就是您之前评论的意思。
    • 如果我只想选择“cmets”的某些元素怎么办?
    • 您只需要添加另一个项目以包含嵌套数组中的某些字段。更新了答案。
    • 如果您需要对嵌套数组文档进行排序,则需要展开。
    猜你喜欢
    • 2017-01-03
    • 2017-07-25
    • 2019-01-19
    • 1970-01-01
    • 2020-03-14
    • 2021-06-17
    • 2023-04-05
    • 2016-01-21
    相关资源
    最近更新 更多