【问题标题】:Lookup nested fields in mongodb array在 mongodb 数组中查找嵌套字段
【发布时间】:2021-07-04 14:45:41
【问题描述】:

架构

[
    {
        "_id" : ObjectId("60e09c90402cbd625d7a8162"),
        "title" : "...",
        "author" : DBRef("users", ObjectId("60ce9146f41866120ee70c0d")),
        "posts" : [ ]
    }
    {
        "_id" : ObjectId("60e09c97402cbd625d7a8163"),
        "title" : "...",
        "author" : DBRef("users", ObjectId("60ce9146f41866120ee70c0d")),
        "posts" : [ ]
    }
    {
        "_id" : ObjectId("60e09d06402cbd625d7a8164"),
        "title" : "...",
        "author" : DBRef("users", ObjectId("60ce9146f41866120ee70c0d")),
        "posts" : [ ]
    }
    {
        "_id" : ObjectId("60e09d07402cbd625d7a8165"),
        "title" : "...",
        "author" : DBRef("users", ObjectId("60ce9146f41866120ee70c0d")),
        "posts" : [
            {
                "_id" : ObjectId("60e12300e931cd14c03ecd89"),
                "title" : "...",
                "author" : DBRef("users", ObjectId("60ce9146f41866120ee70c0d"))
            },
            {
                "_id" : ObjectId("60e12305e931cd14c03ecd8a"),
                "title" : "...",
                "author" : DBRef("users", ObjectId("60ce9146f41866120ee70c0d"))
            }
        ]
    }
]

每个文档都有一个title、author 和posts 属性。 author 属性是 $ref,posts 属性是文档数组。 posts 的每个文档也会有title, author。

我想要什么

我想获取所有带有作者的文档,它是posts(with author)。

查询

db.blogs.aggregate([
  { $project: {title:1,author:1,"posts.title":1,"posts._id":1,"posts.author":1} },
  { "$lookup": { "from": "users", "localField": "author.$id", "foreignField": "_id", "as": "author" } },
  { "$lookup": { "from": "users", "localField": "posts.author.$id", "foreignField": "_id", "as": "posts.author" } }
])

响应

[
  {
    "_id": '..',
    "title": "..",
    "author": [
      {
        // author details
      }
    ],
    "posts": {
      "author": []
    }
  },
  {
    "_id": '..',
    "title": "...",
    "author": [
      {
        // author details
      }
    ],
    "posts": {
      "author": []
    }
  },
  {
    "_id": '..',
    "title": "..",
    "author": [
      {
        // author details
      }
    ],
    "posts": {
      "author": []
    }
  },
  {
    "_id": ...,
    "title": "2 Type SR Blog, my first blog.",
    "author": [
      {
        // author details
      }
    ],
    "posts": {
      "author": [
        {
        // author details
        }
      ]
    }
  }
]

用户集合

{
    "_id" : ObjectId("60ce9146f41866120ee70c0d"),
    "name" : "Rahul kumar",
    "status" : "A Fake Developer",
    "__v" : 0,
    "pic" : "https://res.cloudinary.com/bdevg/image/upload/v1604287418/pic_xexz8o.jpg"
}

问题

你可以看到最后一个文档,它只有posts 属性。它还应该包含title 属性。

【问题讨论】:

  • 您的示例聚合示例显示 $lookup 到一个名为“用户”的集合。我在您的帖子中没有看到这些文档的示例。
  • 您正在执行 2 个 $lookups 并使用覆盖另一个字段的输出字段名称。我的建议是始终使用新的字段名称,而不是覆盖现有的字段名称。此外,第二个 $lookup 正在从集合“用户”中提取数据,该集合可能有也可能没有标题属性 - 您没有提供用户集合中文档的任何示例,但我怀疑用户集合没有名为'title',因此输出中永远不会有一个。
  • @barrypicker 我现在添加了用户收藏。
  • posts 数组文档的作者可以不同于博客作者。所以,我希望帖子的作者被包含为posts.author。
  • 你可以看到,在第二次查找"as": "posts.author" 。

标签: node.js mongodb aggregation-framework


【解决方案1】:
  • $unwind 解构 posts 数组
  • $lookup 与 users 集合并将 posts.author 作为 localField 传递
  • $unwind 解构 author 数组
  • $group by _id 并重构 posts 数组并获取其他必填字段的第一个值
  • $lookup 和 users 并通过 author 作为 localField
  • $unwind 解构author 数组
db.blogs.aggregate([
  {
    $unwind: {
      path: "$posts.author",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    "$lookup": {
      "from": "users",
      "localField": "posts.author",
      "foreignField": "_id",
      "as": "posts.author"
    }
  },
  {
    $unwind: {
      path: "$posts.author",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $group: {
      _id: "$_id",
      title: { $first: "$title" },
      posts: { $push: "$posts" },
      author: { $first: "$author" }
    }
  },
  {
    "$lookup": {
      "from": "users",
      "localField": "author",
      "foreignField": "_id",
      "as": "author"
    }
  },
  {
    $unwind: {
      path: "$author",
      preserveNullAndEmptyArrays: true
    }
  }
])

Playground

【讨论】:

    猜你喜欢
    • 2022-11-11
    • 2015-06-20
    • 2015-05-18
    • 2023-02-01
    • 1970-01-01
    • 2020-12-18
    • 2017-09-30
    • 2021-08-27
    相关资源
    最近更新 更多