首页 > 解决方案 > 如何从聚合中的reduce或map中的文档字段声明变量?

问题描述

我有一个如下集合:

{
  id: 1,
  names: {
    first: 'Ana',
    second: '',
    third: 'Smith',
    four: 'Smitchd'
  },
  used: [
    {
      position: 'first',
      id: 'A'
    },
    {
      position: 'second',
      id: 'B'
    },
  ] 
}

我需要计算有多少used names通过文档收集的集合,不包括那些是空的。

used的位置names保存在一个名为 的数组used中。

在示例中,我需要计算内部存在的名称used,但 innames不为空

我尝试使用reduce 进行聚合来遍历数组used,我可以计算数组中的项目,但我不能使用reduce 中的字段名称。

db.collection.aggregate([
  { $match: id: 1 },
  { $project: { 
    totalUsed: $reduce: {
      input: '$used',
      initialValue: 0,
      in: { $add: ['$$value', { $cond: [{ $eq: ["$$name.$$this.position", '' ]}, 1, 0] }]}
    }
  }}
])

我需要获得未使用空名称的计数...在示例中,我应该得到计数:1,因为即使在使用 first 和 secodn 时,字段 names.second 也是空的。

标签: mongodbmongodb-query

解决方案


我解决了...

我将对象names转换为对象数组({k:key,v:value}),然后我用names(新数组)声明了一个变量used并使用reduce insed of。

我在新数组中查找$$used.positionreduce上的键的索引,然后比较该值是否为“”,并根据情况添加1或0

db.collection.aggregate([
  { $match: id: 1 },
  {
    $project: {
      id: "$id",
      used: { "$used" },
      names: {  $objectToArray : "$names" },
    }
  },
  { 
    $project: {
     totalUsed: {
      $let: {
        vars: { names: "$names", used: "$used" },
        in: {
          $reduce: {
            input: "$$used",
            initialValue: 0,
            in: {
              $add: [
                "$$value",
                  {
                    $cond: [
                      { $eq: [{ $arrayElemAt: ["$$names.v", { $indexOfArray: ["$$names.k", "$$this.position"] } ]}, ""]},
                      0,
                      1
                    ]

                  }
              ]
            }
          }
        }
      }
     }
    }
  },
  {
    $group: { _id: "$id", used: { $sum:"$totalUsed" } }
  }
])

推荐阅读