【问题标题】:MongoDb - How to only return field of nested subdocument when using lookup aggregation?MongoDb - 使用查找聚合时如何只返回嵌套子文档的字段?
【发布时间】:2017-10-25 16:51:59
【问题描述】:

我对 MongoDb 很陌生,所以我习惯了 SQL。 现在我的数据库中有两个集合:

1) 系列(具有嵌套的子文档)

2) 审核(决定参考剧集子文档,因为会有很多评论)

请看这张图片以更好地理解。

现在我想实现以下目标。对于每条评论(在本例中为两条),我想获取剧集名称。

我尝试了以下方法:

db.review.aggregate([  
   {  
      $lookup:{  
         from:"series",
         localField:"episode",
         foreignField:"seasons.episodes._id",
         as:"episode_entry"
      }
   }
]).pretty()

问题在于,这(当然)不仅返回所引用剧集的标题,而且返回整个赛季文档。

查看下图了解我当前的输出。

我不知道如何实现它。请帮我。 我正在使用 Mongo 3.4.9

【问题讨论】:

  • 能否请您以文本格式而不是使用图像发布您的示例数据,以便我们可以复制和粘贴它?另外,您想要的确切输出结构是什么?

标签: mongodb nosql bigdata aggregation-framework nosql-aggregation


【解决方案1】:

我会推荐以下系列结构,它将季节数组展开为每个季节的多个文档。

这将帮助您直接插入/更新剧集。

有点像

db.series.insertMany([
  {
    "title": "Sherlock Holmes",
    "nr": 1,
    "episodes": [
      {
        "title": "A Study in Pink",
        "nr": 1
      },
      {
        "title": "The Blind Banker",
        "nr": 2
      }
    ]
  },
  {
    "title": "Sherlock Holmes",
    "nr": 2,
    "episodes": [
      {
        "title": "A Scandal in Belgravia",
        "nr": 1
      },
      {
        "title": "The Hounds of Baskerville",
        "nr": 2
      }
    ]
  }
])

查找查询会做这样的事情

episode: { $in: [ episodes._id1, episodes._id2, ... ] }

来自文档

如果该字段包含一个数组,则 $in 运算符选择 其字段包含一个数组的文档,该数组至少包含一个 与指定数组中的值匹配的元素(例如 、 等)

因此,查找将在匹配时返回所有剧集。然后,您可以进行过滤以仅保留与您的评论剧集匹配的内容。

所以查询看起来像

db.review.aggregate([
  {
    "$lookup": {
      "from": "series",
      "localField": "episode",
      "foreignField": "episodes._id",
      "as": "episode_entry"
    }
  },
  {
    "$addFields": {
      "episode_entry": [
        {
          "$arrayElemAt": {
            "$filter": {
              "input": {
                "$let": {
                  "vars": {
                    "season": {
                      "$arrayElemAt": [
                        "$episode_entry",
                        0
                      ]
                    }
                  },
                  "in": "$$season.episodes"
                }
              },
              "as": "result",
              "cond": {
                "$eq": [
                  "$$result._id",
                  "$episode"
                ]
              }
            }
          }
        },
        0
      ]
    }
  }
])

【讨论】:

  • 非常感谢您的回答。我还看到人们只为这个用例使用一个集合。您如何看待我将评论与其他评论分开的想法?是因为它的数量是好的做法,还是您更喜欢将它作为子文档放置在剧集条目中。
  • Np。单个文档的存储有 16 MB 的限制。如果您认为在剧集中嵌入评论会达到极限,那么我会将评论保留在自己的收藏中。您还可以对将在单个文档中存储季节、剧集及其评论的文档进行建模。尽量不要在数组中嵌入数组,因为更新/插入值变得困难。有很多方法可以对文档进行建模,但请根据您的用例选择最合适的一种。
  • 您的 $$result._id 错误,因为我需要剧集的 id。目前它是赛季的_id。如何获得更深一层的_id?
  • 对不起,我应该注意到了。更新了答案以包含 $let 表达式以将一个季节的剧集投影到 $filter 聚合。
  • 哇,谢谢!我认为与 sql 相比,MongoDb 过于复杂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-27
  • 2023-03-30
  • 2018-12-14
  • 2021-06-03
  • 2020-03-08
  • 1970-01-01
  • 2021-08-22
相关资源
最近更新 更多