我有2个收藏
products
{
"_id":"1",
"orderId":"1",
"code":"beaf"
},
{
"_id":"2",
"orderId":"1",
"code":"pork"
}
{
"_id":"3",
"orderId":"2",
"code":"beaf"
}
orders
{
"_id":"1",
"paymentMethod": "creditCard"
},
{
"_id":"2",
"paymentMethod": "cash"
}
我需要获取代码为“beaf”并通过“信用卡”支付的产品数量,并以最佳性能获取大约 100 万条记录。
有没有办法分别过滤2个集合,然后匹配(lookup, unionWith)结果以获得更好的性能?
以下解决方案工作正常,但对于 100 万个产品和 80 万个订单大约需要 15 秒。
db.products.aggregate([
{ $match: { code: "beaf" } },
{
$lookup:
{
from: "orders",
localField: "_id",
foreignField: "orderId",
as: "order"
}
},
{
$match: { order.paymentMethod: "creditCard" }
},
{
$count: "count"
}
]);
我认为工作缓慢的原因是订单在查找阶段后被过滤。 分别获取过滤订单和产品的数量需要 <1sec so it does not look like an index issue.
尝试使用“facet”阶段会导致超出文档大小限制。
Here is live example:
https://mongoplayground.net/p/DS2Ble2Z-Ew
您在
$match
之后使用 $lookup
,我认为它将创建 更多计算。 version >= MongoDB 3.6
向前聚合管道中提供了可用的设施,但使用 $expr
运算符可以让您访问聚合运算符,即使在查询中也是如此。
Indexes improve the efficiency of read operations by reducing the amount of data that query operations need to process.
db.products.aggregate([
{
$match: {
code: "pizza"
}
},
{
$lookup: {
from: "orders",
let: {
orderId: "$orderId"
},
pipeline: [
{
$match: {
$expr: {
"$and": [
{
$eq: [
"$_id",
"$$orderId"
]
},
{
$eq: [
"$paymentMethod",
"creditCard"
]
}
]
}
}
}
],
as: "order"
}
},
{
$unwind: "$order"
},
{
"$group": {
"_id": null,
"count": {
"$count": {}
}
}
}
])