【问题标题】:MongoDB Aggregation join array of strings to single stringMongoDB聚合将字符串数组连接到单个字符串
【发布时间】:2020-10-08 17:25:30
【问题描述】:

我们正在尝试将字符串数组“加入”到聚合中的单个字符串。

给出以下数据集:

集合 1:

{
  id: 1234,
  field: 'test'
}

集合 2:

{
  id: 1111,
  collection1_id: 1234,
  name: 'Max'
},
{
  id: 1112,
  collection1_id: 1234,
  name: 'Andy'
}

当前结果(查找等后):

{
  id: 1234,
  field: 'test',
  collection2: ['Max', 'Andy'] 
}

想要的结果:

{
  id: 1234,
  field: 'test',
  collection2: 'Max, Andy'
}

是否有可能将“collection2”加入单个字符串?我们已经尝试使用$concat,但它只接受字符串。

【问题讨论】:

    标签: mongodb aggregation-framework string-concatenation


    【解决方案1】:

    你是在正确的轨道上。

    只需在您的 $project 阶段中​​将 $reduce 添加到 $concat 即可。

    'collection2': {
        '$reduce': {
            'input': '$collection2',
            'initialValue': '',
            'in': {
                '$concat': [
                    '$$value',
                    {'$cond': [{'$eq': ['$$value', '']}, '', ', ']}, 
                    '$$this']
            }
        }
    }
    

    注意:我们使用$cond 来防止串联中的前导,。 您也可以在$reduce 之前使用$substrCP 作为$cond 的替代品。

    【讨论】:

    • mongo 3.2 有什么解决方案吗?我无权访问$reduce
    • @Friedrich 请您详细说明如何使用$substrCP
    【解决方案2】:

    要展平这个数组,您需要将进程转移到客户端。

    mongo 将在新版本中提供一些新的扁平化选项,但 afaik 将是算术选项(avg、min、max....)。

    【讨论】:

      【解决方案3】:

      Mongo 4.4 开始,$group 阶段有一个新的聚合运算符$accumulator,允许在文档分组时自定义累积:

      // { "collectionId" : 1234, "name" : "Max"  }
      // { "collectionId" : 876,  "name" : "Rob"  }
      // { "collectionId" : 1234, "name" : "Andy" }
      db.collection.aggregate([
        { $group: {
          _id: "$collectionId",
          names: {
            $accumulator: {
              accumulateArgs: ["$name"],
              init: function() { return [] },
              accumulate: function(names, name) { return names.concat(name) },
              merge: function(names1, names2) { return names1.concat(names2) },
              finalize: function(names) { return names.join(",") },
              lang: "js"
            }
          }
        }}
      ])
      // { "_id" : 876,  "names" : "Rob"      }
      // { "_id" : 1234, "names" : "Max,Andy" }
      

      累加器:

      • 在场上积累name (accumulateArgs)
      • 初始化为空数组 (init)
      • 通过将新名称连接到已经看到的名称(accumulatemerge)来累积
      • 最后将所有名称连接为字符串 (finalize)

      【讨论】:

        【解决方案4】:

        有时使用 JavaScript 是最简单的:

        db.getCollection('Collection1').aggregate([
        {
           $lookup:
             {
               from: 'Collection2',
               localField: 'id',
               foreignField: 'collection1_id',
               as: 'col2'
             }
        }]).map((e) => ({
          id: e.id,
          field: e.field,
         collection2: Array.isArray(e.col2) &&
           e.col2.reduce((arr, el) => {
             arr.push(el.name);
            return arr;
          }, []).join(', ')
        }))
        

        【讨论】:

          猜你喜欢
          • 2015-02-14
          • 2020-11-27
          • 1970-01-01
          • 2020-07-24
          • 1970-01-01
          • 2020-11-23
          • 1970-01-01
          • 2015-05-07
          • 1970-01-01
          相关资源
          最近更新 更多