我如何执行嵌套的";加入;(加入3个或更多集合)在MongoDB聚合管道中?
假设MongoDB中有3个假设集合:我如何执行嵌套的";加入;(加入3个或更多集合)在MongoDB聚合管道中?,mongodb,nosql,aggregation-framework,nosql-aggregation,Mongodb,Nosql,Aggregation Framework,Nosql Aggregation,假设MongoDB中有3个假设集合:客户,订单,以及订单项 每个客户都有多个订单,每个订单都有多个订单项 以下是这3个集合的一些示例数据: 客户 命令 订单项 期望结果 我如何编写聚合管道,使返回的结果看起来像这样 [ { customer_id: 1, name: "Jim Smith", email: "jim.smith@example.com" orders: [
客户
,订单
,以及订单项
每个客户都有多个订单,每个订单都有多个订单项
以下是这3个集合的一些示例数据:
客户
命令
订单项
期望结果
我如何编写聚合管道,使返回的结果看起来像这样
[
{
customer_id: 1,
name: "Jim Smith",
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
}
]
}
]
},
{
customer_id: 2,
name: "Bob Jones",
email: "bob.jones@example.com"
orders: []
}
]
使用
带有$lookup
集合,订单
,定义来自主集合的变量let
,使用customer\u id
像$$
一样在管道内访问此参考变量$$customer\u id
可以像在根级别管道中一样添加管道阶段pipeline
每当我们匹配内部字段时,它都需要表达式匹配条件,因此$expr
是在$$customer\u id
中声明的父集合字段,let
是子集合/当前集合的字段$customer\u id
与$lookup
集合orderitems
提示: 在NoSQL中有几个连接被认为是不好的做法,我建议如果您可以将订单项作为数组添加到orders集合中,您可以为orderitems保存一个连接过程,请参阅中的改进版本
您能否解释一下
$lookup
管道中的$match
阶段是如何工作的,以及为什么需要它?在本例中,如果您完全删除$match
阶段,结果仍然相同。我已进一步更新了详细信息。您将从附加的$lookup参考链接获得更多帮助,是$match对于根据特定字段加入参考文档是必需的。如果您完全删除$match阶段,结果仍然相同,因为集合中没有其他文档,请添加一些不是父文档引用的虚拟文档。谢谢,我接受了您的回答。最后一件事,有点不相关:通常认为规范化Mongo数据的方式不好,因为它可能需要像这样的几个连接吗?我在这里描述的示例对于SQL来说似乎完全正常,但我不确定是否有更好的方法在Mongo中进行操作。我在回答中添加了一个技巧。
[
{
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_id: 1
},
{
order_item_id: 3,
name: "baz",
price: 24.99,
order_id: 2
}
]
[
{
customer_id: 1,
name: "Jim Smith",
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
}
]
}
]
},
{
customer_id: 2,
name: "Bob Jones",
email: "bob.jones@example.com"
orders: []
}
]
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"
}
}
])