基于过滤器的 Mongo 个子文档中的总数量

Sum Quantity in Mongo Subdocument Based on Filter

我在 MongoDB 中有一个“装运”文档,它具有以下基本结构:

shipment {
   "id": "asdfasdfasdf",
   "shipDate": "2021-04-02",
   "packages": [
        {
            "id": "adfasdfasdfasdf",
            "contents": [
                {
                    "product": {
                        "id": "asdfasdfasdfasd"
                    },
                    "quantity": 10
                }
            ]
        }
    ]
}

请注意,“产品”存储为 DBRef。

我想查找自给定日期以来已发货的特定产品的总数量(基于产品 ID)。我相信这是应该遵循的适当逻辑:

  1. 匹配“shipDate”大于给定日期的货件。
  2. 查找“contents”包含“id”与给定产品 ID 匹配的产品的条目
  3. 将每个匹配条目的“数量”值相加
  4. Return总和

到目前为止,这是我为 Mongo 查询提出的结果:

db.shipment.aggregate([
    {$match: {"shipDate": {$gt: ISODate("2019-01-01")}}},
    {$unwind: "$packages"},
    {$unwind: "$packages.contents"},
    {$unwind: "$packages.contents.product"},
    {
        $project: {
            matchedProduct: {
                $filter: {
                    input: "$packages.contents.products",
                    as: "products",
                    cond: { 
                        "$eq": ["$products.id", ObjectId("5fb55eae3fb1bf783a4fa97f")]
                    }
                }
            }
        }
    }
])

查询有效,但似乎只有 return 所有符合 $match 条件且“产品”值为 null 的条目。

我对 Mongo 查询还很陌生,所以这可能是一个简单的解决方案。但是,我一直无法弄清楚如何 return 匹配产品 ID 的“内容”数量字段的 $sum。

非常感谢任何帮助,谢谢。

查询解决了问题

db.shipment.aggregate([
  {
    $match: {
      "shipDate": {$gte: ISODate("2019-01-01")},
      "packages.contents.product.$id": ObjectId("5fb55eae3fb1bf783a4fa98e")
    }
  },
  { $unwind: "$packages" },
  { $unwind: "$packages.contents" },
  { $unwind: "$packages.contents.product" },
  {
    $match: {
      "packages.contents.product.$id": ObjectId("5fb55eae3fb1bf783a4fa98e")
    }
  },
  {
    $group: {
      "_id": null,
      "total": {
        "$sum": "$packages.contents.quantity"
      }
    }
  }
])

演示 - https://mongoplayground.net/p/c3Ia9L47cJS

使用 { $match: {"packages.contents.product.id": 1 } }, 按产品 ID 过滤记录。

之后将它们分组并找到总数 { $group: {"_id": null,"total": { "$sum": "$packages.contents.quantity" } } }


db.collection.aggregate([
  { $match: {"shipDate": "2021-04-02","packages.contents.product.id": 1 } },
  { $unwind: "$packages" },
  { $unwind: "$packages.contents" },
  { $match: { "packages.contents.product.id": 1 } },
  { $group: { "_id": null,"total": { "$sum": "$packages.contents.quantity" } } }
])

在顶部添加额外检查 { $match: {"shipDate": "2021-04-02","packages.contents.product.id": 1 } } 产品 ID 将仅过滤具有我们需要的产品 ID 的文档,因此查询会更快。


选项-2

演示 - https://mongoplayground.net/p/eo521luylsG

db.collection.aggregate([
  { $match: { "shipDate": "2021-04-02", "packages.contents.product.id": 1 }},
  { $unwind: "$packages" },
  { $project: { contents: { $filter: { input: "$packages.contents", as: "contents",  cond: {"$eq": [  "$$contents.product.id",  1] }}}}},
  { $unwind: "$contents" },
  { $group: { "_id": null,  "total": { "$sum": "$contents.quantity" }}}
])