MongoDB如何按公共字段分组并合并同组文档的指定字段内容
MongoDB 同字段分组拼接解决方案
你可以直接使用MongoDB自带的聚合管道实现需求,不需要额外依赖,完整查询语句如下:
db.collection.aggregate([ // 按paragraph字段分组 { $group: { _id: "$paragraph", // 取同组第一条文档的id作为分组后记录的id originalId: { $first: "$id" }, // 将同组所有text字段存入数组 textArr: { $push: "$text" } } }, // 重构字段结构,拼接text数组为字符串 { $project: { _id: 0, id: "$originalId", paragraph: "$_id", // 用空格拼接所有text,避免开头多余空格 text: { $reduce: { input: "$textArr", initialValue: "", in: { $concat: [ "$$value", { $cond: [{ $eq: ["$$value", ""] }, "", " "] }, "$$this" ] } } } } }, // 按id升序排序 { $sort: { id: 1 } }, // 可选:如果需要将结果持久化为新集合,添加$out阶段 // { $out: "merged_paragraph" } ])
如果你期望最终结果的id是连续递增的1、2、3(和你给出的示例结果一致),可以在排序阶段后新增行号生成逻辑,替换原有id:
{ $setWindowFields: { sortBy: { paragraph: 1 }, output: { id: { $documentNumber: {} } } } }
业务代码层实现(可选)
如果你不想用MongoDB聚合,也可以在业务代码中查询全量数据后手动分组处理,以Node.js为例:
// 查询所有文档 const allDocs = await db.collection.find().sort({ id: 1 }).toArray(); const paragraphMap = new Map(); const result = []; allDocs.forEach(doc => { if (!paragraphMap.has(doc.paragraph)) { const newItem = { id: doc.id, paragraph: doc.paragraph, text: doc.text }; paragraphMap.set(doc.paragraph, newItem); result.push(newItem); } else { paragraphMap.get(doc.paragraph).text += ` ${doc.text}`; } }); // 如需生成连续id,直接遍历result赋值即可 // result.forEach((item, index) => item.id = index + 1)
最终得到的result数组即可直接作为接口响应返回。
内容的提问来源于stack exchange,提问作者Manpreet
相关产品推荐
相关产品推荐

