Mongodb计算查询 - 累积乘法

时间:2018-03-22 14:13:33

标签: mongodb calculation

我最近开始在Mongodb工作POC。我在下面有一个json集合

db.ccpsample.insertMany([
  {
    "ccp_id":1,
    "period":601,
    "sales":100.00
  },
  {
    "ccp_id":1,
    "period":602,
    "growth":2.0,
    "sales":"NULL"    ##sales=100.00*(1+(2.0/100)) -- 100.00 comes from(ccp_id:1 and period=601) 
  },
  {
    "ccp_id":1,
    "period":603,
    "growth":3.0,
    "sales":"NULL"   ##sales=100.00*(1+(2.0/100))**(1+(3.0/100))-- 100.00 comes from(ccp_id:1 and period=601) 2.0 comes from (ccp_id:2 and period=602)  
  },
  {
    "ccp_id":2,
    "period":601,
    "sales":200.00
  },
  {
    "ccp_id":2,
    "period":602,
    "growth":2.0,
    "sales":"NULL"   ##sales=200.00*(1+(2.0/100))
  },
  {
    "ccp_id":2,
    "period":603,
    "growth":3.0,
    "sales":"NULL"   ##same like above
  }
])

我需要通过使用上述文件来计算具有NULL的销售字段,其中ccp_id的匹配条件应该相同且period字段应该等于601.我添加了一行来演示上面集合中销售字段的计算。我试过$ graphlookup但没有运气。你们可以帮助或建议某种方式吗?

1 个答案:

答案 0 :(得分:8)

您可以使用以下聚合:

db.ccpsample.aggregate([
  { $sort: { ccp_id: 1, period: 1 } },
  { 
    $group: {
      _id: "$ccp_id",
      items: { $push: "$$ROOT" },
      baseSale: { $first: "$sales" },
      growths: { $push: "$growth" }
    }
  },
  {
    $unwind: {
      path: "$items",
      includeArrayIndex: "index"
    }
  },
  {
    $project: {
      cpp_id: "$items.cpp_id",
      period: "$items.period",
      growth: "$items.growth",
      sales: {
        $cond: {
          if: { $ne: [ "$items.sales", "NULL" ] },
          then: "$items.sales",
          else: {
            $reduce: {
              input: { $slice: [ "$growths", "$index" ] },
              initialValue: "$baseSale",
              in: { $multiply: [ "$$value", { $add: [1, { $divide: [ "$$this", 100 ] }] } ] }
            }
          }
        }
      }
    }
  }
])

基本上要计算n-th元素的值,你必须知道以下事项:

  • 第一个元素($first中的$group
  • 的销售值
  • 所有growths$push中的$group
  • 的数组
  • n表示您必须执行的乘法次数

要计算索引,您应该将$push所有元素放入一个数组中,然后使用带有includeArrayIndex选项的$unwind,这会将未展开数组的索引插入字段index

最后一步计算累积乘法。它使用$sliceindex字段来评估应该处理多少growths。因此601会有一个元素,602会有两个元素,依此类推。

然后是$reduce处理该数组并根据您的公式执行乘法的时间:(1 + (growth/100)