【问题标题】:Mongo Aggregation - Using variables created in $projectMongo 聚合 - 使用在 $project 中创建的变量
【发布时间】:2014-01-05 12:08:21
【问题描述】:

是否可以在同一阶段使用$project 阶段中​​定义的变量?

例如,我有这个聚合管道:

pipeline = [
  { '$match': {} },
  {
    '$group': {
      '_id': '$_id',
      'n': { '$first': 'n' }
    }
  },
  {
    '$project': {
      'name': 1,
      'n': 1,
      'revenue': { '$multiply': ['$n', 2] },
      'cost': { '$multiply': ['$revenue', 0.25] }
    }
  }
]

我想在同一个$project 阶段使用$revenue 变量(我在$project 中定义)来计算cost 的值,但这不起作用。

有什么方法可以轻松有效地做到这一点?我考虑过做几个预测,但每次我需要计算一个额外的变量时,我都需要投影许多变量(~25 个变量),而且我有一堆变量要计算,它们相互依赖(~5 个变量),而且我的代码可能看起来很糟糕,因为会有很多相同变量的投影。我该怎么办?

【问题讨论】:

    标签: python mongodb pymongo aggregation-framework


    【解决方案1】:

    Mongo 3.4 开始,您可以使用一系列$addFields 阶段而不是冗长的$project 阶段。

    这样,您可以继续投影其他字段,其中一些可以重复使用以前计算的字段:

    // { name: "a", n: 3 }
    // { name: "b", n: 5 }
    db.collection.aggregate([
      { $addFields: { revenue: { $multiply: ["$n", 2] } } },
      { $addFields: { cost: { $multiply: ["$revenue", 0.25] } } } // re-use "revenue"
    ])
    // { name: "a", n: 3, revenue: 6,  cost: 1.5 }
    // { name: "b", n: 5, revenue: 10, cost: 2.5 }
    

    【讨论】:

      【解决方案2】:

      在搜索相同问题时刚刚登陆这里。我目前的解决方案是添加更多 $project 阶段,并始终采用所有其他领域。对于您的示例,它看起来像这样:

      pipeline = [{   
          '$match': {}
      },
      {
          '$group': {
              '_id': '$_id',
              'n': {'$first': 'n'}
      },
      {
          '$project': {
              'name': 1,
              'n': 1,
              'revenue': {'$multiply': ['$n', 2]}
          }
      },
      {
          '$project': {
              'name': 1,
              'n': 1,
              'revenue': 1,
              'cost': {'$multiply': ['$revenue', 0.25]}
          }
      }]
      

      如果您想保留所有以前的计算字段,而无需多次重复使用表达式,我还没有找到更好的解决方案。

      【讨论】:

        【解决方案3】:

        不,但您可以嵌套投影运算符作为解决方法:

        pipeline = [{   
            '$match': {}
        },
        {
            '$group': {
                '_id': '$_id',
                'n': {'$first': 'n'}
        },
        {
            '$project': {
                'name': 1,
                'n': 1,
                'revenue': {'$multiply': ['$n', 2]},
                'cost': {'$multiply': [{'$multiply': ['$n', 2]}, 0.25]}
            }
        }]
        

        在这种情况下,您可以简化为:

        pipeline = [{   
            '$match': {}
        },
        {
            '$group': {
                '_id': '$_id',
                'n': {'$first': 'n'}
        },
        {
            '$project': {
                'name': 1,
                'n': 1,
                'revenue': {'$multiply': ['$n', 2]},
                'cost': {'$multiply': ['$n', 2, 0.25]}
            }
        }]
        

        【讨论】:

        • 是的,但是每个变量都是几行代码,每次计算中都会有很多嵌套变量。每次我需要使用它时,我都需要嵌套变量的计算,如果我有 5 个变量相互依赖,而我必须在每次计算中使用每个变量大约 5 次,这将没有意义。不过谢谢你的建议!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多