mongodb - MongoDB 聚合管道的操作超时
问题描述
我在 MongoDB Atlas 上有一个 MongodDB 数据库。
它有“orders”、“products”、“itemTypes”和“brands”。
- “订单”仅跟踪订购的产品 ID。
- "products" 只记录品牌 id 和 itemType id
- "itemTypes" 跟踪项目类型名称
- “品牌”跟踪品牌名称。
如果我汇总订单 + 产品 + itemTypes 就可以了:
[{
$unwind: {
path: '$orders'
}
}, {
$lookup: {
from: 'products',
localField: 'orders.productId',
foreignField: 'productId',
as: 'products'
}
}, {
$lookup: {
from: 'itemTypes',
localField: 'products.typeId',
foreignField: 'typeId',
as: 'itemTypes'
}
}, {
$set: {
'orders.price': {
$arrayElemAt: ['$products.price', 0]
},
'orders.brandId': {
$arrayElemAt: ['$products.brandId', 0]
},
'orders.typeId': {
$arrayElemAt: ['$products.typeId', 0]
},
'orders.typeName': {
$arrayElemAt: ['$itemTypes.name', 0]
}
}
}, {
$group: {
_id: '$_id',
createdAt: {
$first: '$createdAt'
},
status: {
$first: '$status'
},
retailerId: {
$first: '$retailerId'
},
retailerName: {
$first: '$retailerName'
},
orderId: {
$first: '$orderId'
},
orders: {
$push: '$orders'
}
}
}]
如果我聚合订单 + 产品 + itemTypes + 品牌,无论是 Mongo Compass 还是 Mongo Atlas 聚合构建器的 Web UI 都会出现操作超时错误。
[{
$unwind: {
path: '$orders'
}
}, {
$lookup: {
from: 'products',
localField: 'orders.productId',
foreignField: 'productId',
as: 'products'
}
}, {
$lookup: {
from: 'itemTypes',
localField: 'products.typeId',
foreignField: 'typeId',
as: 'itemTypes'
}
}, {
$lookup: {
from: 'brands',
localField: 'products.brandId',
foreignField: 'brandId',
as: 'brands'
}
}, {
$set: {
'orders.price': {
$arrayElemAt: ['$products.price', 0]
},
'orders.brandId': {
$arrayElemAt: ['$products.brandId', 0]
},
'orders.typeId': {
$arrayElemAt: ['$products.typeId', 0]
},
'orders.typeName': {
$arrayElemAt: ['$itemTypes.name', 0]
},
'orders.brandName': {
$arrayElemAt: ['$brands.name', 0]
}
}
}, {
$group: {
_id: '$_id',
createdAt: {
$first: '$createdAt'
},
status: {
$first: '$status'
},
retailerId: {
$first: '$retailerId'
},
retailerName: {
$first: '$retailerName'
},
orderId: {
$first: '$orderId'
},
orders: {
$push: '$orders'
}
}
}]
这是超时聚合的演示:
https://mongoplayground.net/p/Jj6EhSl58MS
我们有大约 50,000 个订单,14,000 种产品,200 个品牌,89 种商品类型。
无论如何要优化此聚合以使其不会超时?
P/s:我的最终目标是在 Mongodb Charts 功能中使用漂亮的图表可视化流行的品牌和项目类型。
解决方案
如果您在 Mongo Atlas 上,您可以使用 Triggers 在后台运行聚合查询 - 无论是在数据库更新时还是作为计划的触发器 ( https://docs.mongodb.com/realm/triggers/ )。
当触发器运行时,您可以使用“$merge”操作将聚合管道的结果保存在新集合中。
exports = function() {
const mongodb = context.services.get(CLUSTER_NAME);
const orders = mongodb.db(DATABASE_NAME).collection("orders");
const ordersSummary = mongodb.db(DATABASE_NAME).collection("orders.summary");
const pipeline = [
{
YOUR_PIPELINE
},
{ $merge: { into: "orders.summary", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }
];
orders.aggregate(pipeline);
};
这样,您的图表将非常快,因为它们只需从新集合中进行简单查询。
推荐阅读
- python-3.x - 检测图像中的线线交叉点?
- python - 是否可以修改现有分布式客户端中的工作程序/线程数?
- c++ - 大型项目中的堆与堆栈分配
- firebase - Dart - 如何让 StreamBuilder 停止监听事件
- sql-server - 如何强制 SSIS 包不重用执行计划?
- strapi - Strapi 可以安装在 Dreamhost 之类的共享服务器上吗?
- powershell - PSGSuite:按创建日期过滤 Google 帐户
- sql - 如何通过加法将值更新为相同的值?
- python - 如何将python脚本的输出保存为json而不是对象流?
- python - 创建一个 3x3 矩阵的 n 维 NumPy 数组