MongoDb - 如何在使用查找聚合时仅返回嵌套子文档的字段?

时间:2017-10-25 16:52:00

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

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

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

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

请参阅此图片以便更好地理解。

enter image description here

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

我尝试了以下内容:

.

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

请参阅下面的图片了解我当前的输出。

enter image description here

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

1 个答案:

答案 0 :(得分: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
      ]
    }
  }
])