Concat字符串(按组) [英] Concat String by Group

查看:51
本文介绍了Concat字符串(按组)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想按_id对记录进行分组,并通过组合client_id值来创建字符串.

I want to group records by _id and create a string by combining client_id values.

以下是我的文档示例:

{
  "_id" : ObjectId("59e955e633d64c81875bfd2f"),
  "tag_id" : 1,
  "client_id" : "10001"
}
{
  "_id" : ObjectId("59e955e633d64c81875bfd30"),
  "tag_id" : 1,
  "client_id" : "10002"
}

我想要这个输出:

{
  "_id" : 1
  "client_id" : "10001,10002"
}

推荐答案

您可以使用聚合框架将其作为两步操作"进行操作.首先通过 $push 使用 $group 管道,然后使用 $concat

You can do it with the aggregation framework as a "two step" operation. Which is to first accumulate the items to an array via $push withing a $group pipeline, and then to use $concat with $reduce on the produced array in final projection:

db.collection.aggregate([
  { "$group": {
    "_id": "$tag_id",
    "client_id": { "$push": "$client_id" }
  }},
  { "$addFields": {
    "client_id": {
      "$reduce": {
        "input": "$client_id",
        "initialValue": "",
        "in": {
          "$cond": {
            "if": { "$eq": [ "$$value", "" ] },
            "then": "$$this",
            "else": {
              "$concat": ["$$value", ",", "$$this"]
            }
          }
        }
      }
    }
  }}
])

我们还在此处应用 $cond 以避免串联结果中带有逗号的空字符串,因此它看起来更像是定界列表.

We also apply $cond here to avoid concatenating an empty string with a comma in the results, so it looks more like a delimited list.

仅供参考,JIRA问题 SERVER-29339 确实要求 $reduce 可以作为 $push 中的内容,并使该操作成为单个管道阶段.提议的示例语法在JIRA问题上.

FYI There is an JIRA issue SERVER-29339 which does ask for $reduce to be implemented as an accumulator expression to allow it's use directly in a $group pipeline stage. Not likely to happen any time soon, but it theoretically would replace $push in the above and make the operation a single pipeline stage. Sample proposed syntax is on the JIRA issue.

如果您没有 $reduce (需要MongoDB 3.4),然后只需处理游标:

If you don't have $reduce ( requires MongoDB 3.4 ) then just post process the cursor:

db.collection.aggregate([
  { "$group": {
    "_id": "$tag_id",
    "client_id": { "$push": "$client_id" }
  }},
]).map( doc =>
  Object.assign(
    doc,
   { "client_id": doc.client_id.join(",") }
  )
)

然后使用 mapReduce 如果您确实必须:

Which then leads to the other alternative of doing this using mapReduce if you really must:

db.collection.mapReduce(
  function() {
    emit(this.tag_id,this.client_id);
  },
  function(key,values) {
    return [].concat.apply([],values.map(v => v.split(","))).join(",");
  },
  { "out": { "inline": 1 } }
)

当然会以_idvalue的特定mapReduce形式作为键集输出,但基本上是输出.

Which of course outputs in the specific mapReduce form of _id and value as the set of keys, but it is basically the output.

我们使用[].concat.apply([],values.map(...))是因为"reducer"的输出可以是定界字符串",因为mapReduce可以递增地工作并获得较大的结果,因此,reducer的输出可以在另一遍通过中成为"input".因此,我们需要期望这会发生并相应地进行处理.

We use [].concat.apply([],values.map(...)) because the output of the "reducer" can be a "delimited string" because mapReduce works incrementally with large results and therefore output of the reducer can become "input" on another pass. So we need to expect that this can happen and treat it accordingly.

这篇关于Concat字符串(按组)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆