MongoDB。从两个集合中查询数据并在两个集合中进行过滤

问题描述 投票:0回答:1

我有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”阶段会导致超出文档大小限制。

mongodb collections aggregate
1个回答
0
投票

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": {}
      }
    }
  }
])
© www.soinside.com 2019 - 2024. All rights reserved.