MongoDB聚合然后展平
MongoDB aggregate and then flatten
完全披露:我是一个 MongoDB 菜鸟
我正在处理遗留数据库结构。我的 MongoDB 的一部分目前看起来像这样:
- 事件(_id、名称(字符串)、...)
- 订单(_id,eventId(字符串),产品({prodIdentifier(字符串)数组,数量(数字)}),customer_ID(字符串),signee(字符串),sign_time(日期),...)
- 产品(_id、prodIdentifier(字符串)、价格(数字)、sku(字符串),...)
关系如下:
- 事件 1..N 订单(通过 eventId)
- 订单 1..N 产品(通过产品数组)
我需要以给定 eventId 的方式进行查询,我 return
Order ID
Customer Name (can be a cascade request / premeditated
by frontend),
Product SKU,
Product Name,
Quantity,
Value (quantity * price),
Signee Name,
Sign time
请注意,我的界面需要对上述所有字段进行过滤和排序,以及分页的限制和偏移量,以减少查询时间、快速 UI 等
我可以在订单上使用 populate
,但我应该如何通过 mongoose 遵守限制和抵消。我想知道我是否应该制作一个视图,在这种情况下我应该如何将它展平为 send/receive 一个遵守限制和偏移量的列表。
还是必须非常手动地逐步构建结果列表?
更新:
数据库中的示例数据:
事件对象:
{
"_id" : ObjectId("6218b9266487367ba1c20258"),
"name" : "XYZ",
"createdAt" : ISODate("2022-02-03T13:25:43.814+0000"),
"updatedAt" : ISODate("2022-02-14T09:34:47.819+0000"),
...
}
订单:
[
{
"_id" : ObjectId("613ae653d0112f6b49fdd437"),
"orderItems" : [
{
"quantity" : NumberInt(2),
"productCode" : "VEO001",
},
{
"quantity" : NumberInt(2),
"productCode" : "VEO002",
},
{
"quantity" : NumberInt(1),
"productCode" : "VEO003",
}
],
"orderCode" : "1000",
"customerCode" : "Customer 1",
"createdAt" : ISODate("2021-09-10T05:00:03.496+0000"),
"updatedAt" : ISODate("2022-02-08T10:06:42.255+0000"),
"eventId" : "6218b9266487367ba1c20258"
}
]
产品:
[
{
"_id" : ObjectId("604206685f25b8560a1cd48d"),
"Product name" : "ABC",
"createdAt" : ISODate("2021-03-05T10:22:32.085+0000"),
"tag" : "VEO001",
"updatedAt" : ISODate("2022-03-28T07:29:21.939+0000"),
"Product Price" : NumberInt(0),
"photo" : {
"_id" : ObjectId("6042071a5f25b8560a1cd4a9"),
"key" : "e8c9a085-4e8d-4ac4-84e9-bb0a83a59145",
"name" : "Screenshot 2021-03-05 at 11.24.50.png"
},
"name" : "ABC",
"_costprice" : NumberInt(12),
"_sku" : "SKUVEO001",
},
{
"_id" : ObjectId("604206685f25b8560a1cd48a"),
"Product name" : "DEF",
"createdAt" : ISODate("2021-03-05T10:22:32.085+0000"),
"tag" : "VEO002",
"updatedAt" : ISODate("2022-03-28T07:29:21.939+0000"),
"Product Price" : NumberInt(0),
"photo" : {
"_id" : ObjectId("6042071a5f25b8560a1cd4a9"),
"key" : "e8c9a085-4e8d-4ac4-84e9-bb0a83a59145",
"name" : "Screenshot 2021-03-05 at 11.24.50.png"
},
"name" : "DEF",
"_costprice" : NumberInt(13),
"_sku" : "SKUVEO002",
},
{
"_id" : ObjectId("604206685f25b8560a1cd48a"),
"Product name" : "GHI",
"createdAt" : ISODate("2021-03-05T10:22:32.085+0000"),
"tag" : "VEO003",
"updatedAt" : ISODate("2022-03-28T07:29:21.939+0000"),
"Product Price" : NumberInt(0),
"photo" : {
"_id" : ObjectId("6042071a5f25b8560a1cd4a9"),
"key" : "e8c9a085-4e8d-4ac4-84e9-bb0a83a59145",
"name" : "Screenshot 2021-03-05 at 11.24.50.png"
},
"name" : "GHI",
"_costprice" : NumberInt(13),
"_sku" : "SKUVEO003",
},
]
预期输出:
您可以这样做:
db.orders.aggregate([
{$match: {eventId: "6218b9266487367ba1c20258"}},
{
$lookup: {
from: "products",
localField: "orderItems.productCode",
foreignField: "tag",
as: "orderItemsB"
}
},
{
"$addFields": {
"orderItems": {
"$map": {
"input": "$orderItemsB",
"in": {
"$mergeObjects": [
"$$this",
{
"$arrayElemAt": [
"$orderItems",
{"$indexOfArray": ["$orderItems.productCode", "$$this.tag"]}
]
}
]
}
}
},
orderItemsB: 0
}
},
{
$unset: "orderItemsB"
},
{
$lookup: {
from: "events",
let: {eventId: "$eventId"},
pipeline: [
{
$match: {$expr: {$eq: [{$toString: "$_id"}, "$$eventId"]}}
}
],
as: "event"
}
},
{
$set: {event: {"$arrayElemAt": ["$event", 0]}}
},
{$unwind: "$orderItems"}
])
正如您在 this playground example 上看到的那样。这将为您提供包含所有数据的订单中每个产品的文档。
完全披露:我是一个 MongoDB 菜鸟
我正在处理遗留数据库结构。我的 MongoDB 的一部分目前看起来像这样:
- 事件(_id、名称(字符串)、...)
- 订单(_id,eventId(字符串),产品({prodIdentifier(字符串)数组,数量(数字)}),customer_ID(字符串),signee(字符串),sign_time(日期),...)
- 产品(_id、prodIdentifier(字符串)、价格(数字)、sku(字符串),...)
关系如下:
- 事件 1..N 订单(通过 eventId)
- 订单 1..N 产品(通过产品数组)
我需要以给定 eventId 的方式进行查询,我 return
Order ID
Customer Name (can be a cascade request / premeditated by frontend),
Product SKU,
Product Name,
Quantity,
Value (quantity * price),
Signee Name,
Sign time
请注意,我的界面需要对上述所有字段进行过滤和排序,以及分页的限制和偏移量,以减少查询时间、快速 UI 等
我可以在订单上使用 populate
,但我应该如何通过 mongoose 遵守限制和抵消。我想知道我是否应该制作一个视图,在这种情况下我应该如何将它展平为 send/receive 一个遵守限制和偏移量的列表。
还是必须非常手动地逐步构建结果列表?
更新:
数据库中的示例数据:
事件对象:
{
"_id" : ObjectId("6218b9266487367ba1c20258"),
"name" : "XYZ",
"createdAt" : ISODate("2022-02-03T13:25:43.814+0000"),
"updatedAt" : ISODate("2022-02-14T09:34:47.819+0000"),
...
}
订单:
[
{
"_id" : ObjectId("613ae653d0112f6b49fdd437"),
"orderItems" : [
{
"quantity" : NumberInt(2),
"productCode" : "VEO001",
},
{
"quantity" : NumberInt(2),
"productCode" : "VEO002",
},
{
"quantity" : NumberInt(1),
"productCode" : "VEO003",
}
],
"orderCode" : "1000",
"customerCode" : "Customer 1",
"createdAt" : ISODate("2021-09-10T05:00:03.496+0000"),
"updatedAt" : ISODate("2022-02-08T10:06:42.255+0000"),
"eventId" : "6218b9266487367ba1c20258"
}
]
产品:
[
{
"_id" : ObjectId("604206685f25b8560a1cd48d"),
"Product name" : "ABC",
"createdAt" : ISODate("2021-03-05T10:22:32.085+0000"),
"tag" : "VEO001",
"updatedAt" : ISODate("2022-03-28T07:29:21.939+0000"),
"Product Price" : NumberInt(0),
"photo" : {
"_id" : ObjectId("6042071a5f25b8560a1cd4a9"),
"key" : "e8c9a085-4e8d-4ac4-84e9-bb0a83a59145",
"name" : "Screenshot 2021-03-05 at 11.24.50.png"
},
"name" : "ABC",
"_costprice" : NumberInt(12),
"_sku" : "SKUVEO001",
},
{
"_id" : ObjectId("604206685f25b8560a1cd48a"),
"Product name" : "DEF",
"createdAt" : ISODate("2021-03-05T10:22:32.085+0000"),
"tag" : "VEO002",
"updatedAt" : ISODate("2022-03-28T07:29:21.939+0000"),
"Product Price" : NumberInt(0),
"photo" : {
"_id" : ObjectId("6042071a5f25b8560a1cd4a9"),
"key" : "e8c9a085-4e8d-4ac4-84e9-bb0a83a59145",
"name" : "Screenshot 2021-03-05 at 11.24.50.png"
},
"name" : "DEF",
"_costprice" : NumberInt(13),
"_sku" : "SKUVEO002",
},
{
"_id" : ObjectId("604206685f25b8560a1cd48a"),
"Product name" : "GHI",
"createdAt" : ISODate("2021-03-05T10:22:32.085+0000"),
"tag" : "VEO003",
"updatedAt" : ISODate("2022-03-28T07:29:21.939+0000"),
"Product Price" : NumberInt(0),
"photo" : {
"_id" : ObjectId("6042071a5f25b8560a1cd4a9"),
"key" : "e8c9a085-4e8d-4ac4-84e9-bb0a83a59145",
"name" : "Screenshot 2021-03-05 at 11.24.50.png"
},
"name" : "GHI",
"_costprice" : NumberInt(13),
"_sku" : "SKUVEO003",
},
]
预期输出:
您可以这样做:
db.orders.aggregate([
{$match: {eventId: "6218b9266487367ba1c20258"}},
{
$lookup: {
from: "products",
localField: "orderItems.productCode",
foreignField: "tag",
as: "orderItemsB"
}
},
{
"$addFields": {
"orderItems": {
"$map": {
"input": "$orderItemsB",
"in": {
"$mergeObjects": [
"$$this",
{
"$arrayElemAt": [
"$orderItems",
{"$indexOfArray": ["$orderItems.productCode", "$$this.tag"]}
]
}
]
}
}
},
orderItemsB: 0
}
},
{
$unset: "orderItemsB"
},
{
$lookup: {
from: "events",
let: {eventId: "$eventId"},
pipeline: [
{
$match: {$expr: {$eq: [{$toString: "$_id"}, "$$eventId"]}}
}
],
as: "event"
}
},
{
$set: {event: {"$arrayElemAt": ["$event", 0]}}
},
{$unwind: "$orderItems"}
])
正如您在 this playground example 上看到的那样。这将为您提供包含所有数据的订单中每个产品的文档。