【问题标题】:how to sum values according to previous document's value and next document's value in mongodb aggregate?如何根据mongodb聚合中上一个文档的值和下一个文档的值对值求和?
【发布时间】:2020-07-23 20:58:45
【问题描述】:

我正在努力使用 mongodb 中的一些聚合函数。

假设我在两个集合中有一些这样的文档:

集合 A:

{index: "1", time: 10:30:00, value: 12}
{index: "2", time: 10:30:20, value: 11}
{index: "1", time: 10:30:32, value: 15}
{index: "2", time: 10:31:05, value: 13}
{index: "1", time: 10:31:40, value: 14}
{index: "2", time: 10:31:43, value: 10}

集合 B:

{index: "1", time: 10:30:10, cost: 10}
{index: "2", time: 10:30:15, cost: 12}
{index: "1", time: 10:30:30, cost: 8}
{index: "2", time: 10:30:50, cost: 9}
{index: "1", time: 10:31:10, cost: 10}
{index: "2", time: 10:31:23, cost: 11}

我想返回这个:

{index: "1", value: 12, totalCost: 18}
{index: "1", value: 15, totalCost: 10}
{index: "1", value: 14, totalCost: 0}
{index: "2", value: 11, totalCost: 9}
{index: "2", value: 13, totalCost: 9}
{index: "2", value: 10, totalCost: 11}

结果的{index: "1", value: 12, totalCost: 18}意思是:

根据集合A的index=“1”的文档,时间在10:30:00到10:30:32之间,查询集合B的文档index=“1”,时间在10:30:00到10:30:00到10:30:32 然后将其成本加总为totalCost。

mongodb聚合可以实现吗?谢谢!

【问题讨论】:

    标签: mongodb aggregation-framework aggregate


    【解决方案1】:

    好吧,我们需要使用几个运算符。

    顺便说一句:请提供有效的期望,因为您基于样本数据的结果是错误的

    {index: "1", value: 12, totalCost: 18} -> OK
    {index: "1", value: 14, totalCost: 0}  -> OK
    {index: "1", value: 15, totalCost: 10} -> OK
    {index: "2", value: 10, totalCost: 11} -> KO (No B document greater than 10:31:43)
    {index: "2", value: 11, totalCost: 9}  -> OK
    {index: "2", value: 13, totalCost: 9}  -> KO (For 10:31:05 - 10:31:43, matchs only {index: "2", time: 10:31:23, cost: 11})
    

    流水线说明

    1. $graphLookup 用于为给定的index 值构造层次结构。
    2. 我们需要从层次结构中删除:
      • 与父节点具有相同_id 的节点
      • 所有低于父级time的子级
      • 取最接近的time 与父母的time
    3. 我们加入收藏B并采取项目:
      • indexA 文档相同
      • B 的 time 在 A 的父 time 和 A 的子 time 之间
    4. 转换成想要的结果,求和totalCost

    db.A.aggregate([
      {
        $graphLookup: {
          from: "A",
          startWith: "$index",
          connectFromField: "index",
          connectToField: "index",
          as: "range"
        }
      },
      {
        $addFields: {
          range: {
            $reduce: {
              input: "$range",
              initialValue: {
                index: "$index",
                time: "23:59:59",
                value: 0
              },
              in: {
                $cond: [
                  {
                    $and: [
                      {
                        $ne: [ "$_id", "$$this._id" ]
                      },
                      {
                        $gt: [ "$$this.time", "$time" ]
                      },
                      {
                        $lt: [ "$$this.time", "$$value.time" ]
                      }
                    ]
                  },
                  "$$this",
                  "$$value"
                ]
              }
            }
          }
        }
      },
      {
        $lookup: {
          from: "B",
          let: {
            index: "$index",
            start: "$time",
            end: "$range.time"
          },
          pipeline: [
            {
              $match: {
                $expr: {
                  $and: [
                    {
                      $eq: [ "$$index", "$index" ]
                    },
                    {
                      $and: [
                        {
                          $gt: [ "$time", "$$start" ]
                        },
                        {
                          $lt: [ "$time", "$$end" ]
                        }
                      ]
                    }
                  ]
                }
              }
            }
          ],
          as: "linked"
        }
      },
      {
        $project: {
          _id: 0,
          index: 1,
          value: 1,
          totalCost: { $sum: "$linked.cost" }
        }
      },
      {
        $sort: {
          index: 1,
          value: 1
        }
      }
    ])
    

    MongoPlayground

    【讨论】:

      猜你喜欢
      • 2023-03-17
      • 2021-02-01
      • 2020-01-27
      • 2021-12-15
      • 2021-04-13
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      相关资源
      最近更新 更多