【问题标题】:How to join multiple mongoDB Collections如何加入多个 mongoDB 集合
【发布时间】:2022-01-01 15:58:27
【问题描述】:

这里有三个系列。

类别

category: [
    {
      id: 1,
      name: "cat 1",
      status:true
    },
    {
      id: 2,
      name: "cat 2",
      status:true
    }
  ]

物品

item: [
    {
      id: 1,
      name: "item 1"
    },
    {
      id: 2,
      name: "item 2"
    },
    {
      id: 3,
      name: "item 3"
    },
    {
      id: 4,
      name: "item 4"
    }
  ]

[
    {
      id: 1,
      name: "package 1",
      categoryId: 1,
      items: [
        {
          _id: 1,
          itemId: 1
        },
        {
          _id: 2,
          itemId: 2
        }
      ]
    },
    {
      id: 2,
      name: "package 2",
      categoryId: 2,
      items: [
        {
          _id: 1,
          itemId: 3
        },
        {
          _id: 2,
          itemId: 4
        }
      ]
    }
  ]

我想在类别方面获得所有packagesitems object,并且每个类别的状态都应该是真实的。我想根据类别列出所有包。

集合包的CategoryId列是外键

集合包的列ItemId是外键。

预期输出

[
    {
        name:'cat 1',
        status:true,
        package:[
            {
                id: 1,
                name: "package 1",
                categoryId: 1,
                items: [
                    {
                        id: 1,
                        name: "item 1"
                    },
                    {
                        id: 2,
                        name: "item 2"
                    },
                ]
            }
        ]
    },
    {
        name:'cat 2',
        status:true,
        package:[
            {
                id: 2,
                name: "package 2",
                categoryId: 2,
                items: [
                    {
                        id: 3,
                        name: "item 3"
                    },
                    {
                        id: 4,
                        name: "item 4"
                    },
                ]
            }
        ]
    }
]

供参考:https://mongoplayground.net/p/83z0Hcgh04i

【问题讨论】:

标签: mongodb mongoose mongodb-query nodes


【解决方案1】:

为了达到预期的结果,我们必须对数据执行一些步骤,我们将解释每个步骤。你可以看到完整的查询here

我们必须在category DB 上使用的操作是aggregation

db.category.aggregate([])

在这个函数中,我们将每个步骤放入数组中。 第一个是lookup,我们将获取与每个类别匹配的包并将它们存储在packages字段中

{
    "$lookup": {
      "from": "package",
      "localField": "id",
      "foreignField": "categoryId",
      "as": "packages"
    }
}

由于我们需要物品信息来填充每个物品并且物品都在每个包裹内,因此我们必须将它们分开。我们将unwind包裹和物品。

  {
    "$unwind": "$packages"
  },
  {
    "$unwind": "$packages.items"
  }

现在我们可以将每个项目与他的信息进行匹配,与另一个lookup 匹配并将它们存储在每个包中。

  {
    "$lookup": {
      "from": "items",
      "localField": "packages.items.itemId",
      "foreignField": "id",
      "as": "packages.items"
    }
  }

因为做一个lookup给我们一个数组,我们将使用另一个unwind来确保在摸索之前每个文档只有一个项目。

  {
    "$unwind": "$packages.items"
  }

此时我们已经有了我们想要的所有日期,但我们必须再次对其进行分组,因为我们之前用unwind 将其分开。为此,我们将在 packages.id 上使用 group。我们将格式化我们想要的字段,将所有项目推送到一起,并将一些辅助数据保存在 root 字段中以供以后使用。

  {
    "$group": {
      "_id": "$packages.id",
      name: {
        "$first": "$packages.name"
      },
      "brandId": {
        "$first": "$packages.brandId"
      },
      "categoryId": {
        "$first": "$packages.categoryId"
      },
      root: {
        "$first": "$$ROOT"
      },
      "items": {
        "$push": "$packages.items"
      }
    }
  }

在这一步我们将所有的包放在一起,我们必须groupa 获得category。为此,我们将使用root 中的辅助数据存储。

  {
    "$group": {
      "_id": "$root.id",
      name: {
        "$first": "$root.name"
      },
      "packages": {
        "$push": "$$ROOT"
      }
    }
  }

最后我们将删除 aux root 字段。

  {
    "$project": {
      "packages.root": 0
    }
  }

【讨论】:

  • 但是 items 对象应该是 json 对象而不是 json 数组。
  • 现在它的项目": [ [ { "_id": ObjectId("5a934e000102030405000004"), "id": 3, "name": "item 3" } ], [ { "_id": ObjectId("5a934e000102030405000005"), "id": 4, "name": "item 4" } ] ],
  • 你是对的,我编辑了答案,添加了另一个$unwind 步骤以避免这种情况。
猜你喜欢
  • 2021-11-04
  • 1970-01-01
  • 2018-06-23
  • 2020-04-13
  • 2016-06-19
  • 2020-09-11
  • 2020-05-12
  • 2017-08-10
相关资源
最近更新 更多