mongodb - 按组连接字符串

标签 mongodb group-by aggregation-framework concat

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

以下是我的文档示例:

{
  "_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$reduce在最终投影中生成的阵列上:

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此处是为了避免在结果中将空字符串与逗号连接起来,因此它看起来更像是一个分隔列表。

仅供引用,存在 JIRA 问题 SERVER-29339这确实要求 $reduce将作为 accumulator expression 实现允许它直接在 $group 中使用流水线阶段。不太可能很快发生,但理论上它会取代 $push在上面并使操作成为单个管道阶段。建议语法示例在 JIRA 问题上。

如果你没有 $reduce (需要 MongoDB 3.4)然后只对游标进行后处理:

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

这会导致使用 mapReduce 执行此操作的另一种选择如果你真的必须:

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 形式输出,但它基本上是输出。

我们使用 [].concat.apply([],values.map(...)) 因为“reducer”的输出可以是一个“定界字符串”,因为 mapReduce 以增量方式处理大量结果,因此 reducer 的输出可以在另一遍中变成“输入”。因此,我们需要预料到这会发生并相应地对待它。

关于mongodb - 按组连接字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46841825/

相关文章:

javascript - MongoDB -- client.open() 返回 "undefined in not a function"

mongodb - 获取运行日期差异

mysql - Group By 来查找 SQL 中表元素之间的差异?

MongoDB:将多个数值连接到字符串

mongodb - 使用 mongo 查找某人在未来 30 天内是否过生日

spring mongodb聚合求和计数

mongodb - 增加 Mongo BSON 对象的最大大小会导致 Boost 库编译错误

node.js - 如何在Windows上通过crontab或cron作业运行Shell脚本

sql - 计数为零的项目列表不存在

python - 为什么我无法获得 Python 迭代器的倒数第二个结果?