微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 MongoDB 聚合管道中执行嵌套的“连接”连接 3 个或更多集合? 客户订单订单项想要的结果

如何解决如何在 MongoDB 聚合管道中执行嵌套的“连接”连接 3 个或更多集合? 客户订单订单项想要的结果

假设我们在 MongoDB 中有 3 个假设集合:customersordersorderItems

每个客户有多个订单,每个订单有多个订单商品。

以下是这 3 个集合的一些示例数据:

客户

[
    {
        customer_id: 1,name: "Jim Smith",email: "jim.smith@example.com"
    },{
        customer_id: 2,name: "Bob Jones",email: "bob.jones@example.com"
    }
]

订单

[
    {
        order_id: 1,customer_id: 1
    },{
        order_id: 2,customer_id: 1
    }
]

订单项

[
    {
        order_item_id: 1,name: "Foo",price: 4.99,order_id: 1
    },{
        order_item_id: 2,name: "Bar",price: 17.99,{
        order_item_id: 3,name: "baz",price: 24.99,order_id: 2
    }
]

想要的结果

如何编写聚合管道,使返回的结果看起来像这样?

[
    {
        customer_id: 1,email: "jim.smith@example.com"
        orders: [
            {
                order_id: 1,items: [
                    {
                        name: "Foo",price: 4.99
                    },{
                        name: "Bar",price: 17.99
                    }
                ]
            },{
                order_id: 2,items: [
                    {
                        name: "baz",price: 24.99
                    }
                ]
            }
        ]
    },email: "bob.jones@example.com"
        orders: []
    }
]

解决方法

使用 lookup with pipeline 进行嵌套查找,

  • $lookuporders 集合,
    • let,定义来自主集合的变量customer_id,使用$$(如$$customer_id)访问管道内的这个引用变量,
    • pipeline 可以像在根级管道中一样添加管道阶段
    • $expr 每当我们匹配内部字段时,它都需要表达式匹配条件,因此 $$customer_id 是在 let 中声明的父集合字段,$customer_id 是子集合/当前集合的字段
  • $lookuporderitems 集合
db.customers.aggregate([
  {
    $lookup: {
      from: "orders",let: { customer_id: "$customer_id" },pipeline: [
        { $match: { $expr: { $eq: ["$$customer_id","$customer_id"] } } },{
          $lookup: {
            from: "orderitems",localField: "order_id",foreignField: "order_id",as: "items"
          }
        }
      ],as: "orders"
    }
  }
])

Playground


提示:

几种连接在 NoSQL 中被认为是不好的做法,我建议您是否可以将订单项作为数组添加到订单集合中,您可以为订单项节省一个连接过程,请参阅 playground 中的改进版本

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。