MongoDB聚合:如何拼接字符串与数组元素并实现预期输出?
问题描述
现有MongoDB集合结构如下:
[ { "_id": { "$oid": "6332dda58121948311cbdb67" }, "date": "2022-09-13", "file": "xxx", "package": 1, "userList": [ { "userName": "user_1", "crDate": "2022.09.28", "boolId": 1 } ] }, { "_id": { "$oid": "6332dda58121948311cbdb68" }, "date": "2022-09-13", "file": "xxx", "package": 2, "userList": [] } ]
期望输出分两种情况:
- 所有
userList数组为空时:
[ { "_id": "2022-09-13", "items": [ { "fileName": "xxx", "items": [ { "package": "1 - na" }, { "package": "2 - na" } ] } ] } ]
userList数组包含对象时:
[ { "_id": "2022-09-13", "items": [ { "fileName": "xxx", "items": [ { "package": "1 - user_1" }, { "package": "2 - na" } ] } ] } ]
当前执行的聚合脚本存在以下问题:
db.collection.aggregate([ { $group: { _id: { "date": "$date", "file": "$file", }, "items": { $push: { "package": { $concat: [ { $toString: "package" }, " - ", { $toString: { $arrayElemAt: [ "$userList", 0 ] } } ] } } } } }, { $group: { _id: "$_id.date", "items": { $push: { "fileName": "$_id.file", "items": "$items" } } }, } ])
userList非空时抛出错误:Mongo Server error (MongoCommandException): Command failed with error 241 (ConversionFailure): 'Unsupported conversion from object to string in $convert with no onError value',原因是直接对userList的元素(对象)执行$toString,MongoDB不支持将对象转为字符串。userList为空时输出不符合预期,无法返回na标识。
修改后的聚合脚本
db.collection.aggregate([ // 预处理每个文档的package显示文本 { $addFields: { packageText: { $concat: [ { $toString: "$package" }, " - ", // 判断userList是否为空,取第一个元素的userName,否则返回"na" { $cond: { if: { $ne: [{ $size: "$userList" }, 0] }, then: { $getField: { field: "userName", input: { $arrayElemAt: ["$userList", 0] } } }, else: "na" } } ] } } }, // 按date和file分组,收集package项 { $group: { _id: { date: "$date", file: "$file" }, items: { $push: { package: "$packageText" } } } }, // 按date分组,整理最终结构 { $group: { _id: "$_id.date", items: { $push: { fileName: "$_id.file", items: "$items" } } } } ])
修改说明
- 新增
$addFields阶段:提前处理每个文档的packageText字段,解决原脚本中直接转换对象的问题:- 用
$size判断userList是否为空; - 非空时通过
$arrayElemAt取第一个元素,再用$getField提取userName字段; - 为空时直接返回
na; - 最后通过
$concat拼接成目标格式的字符串。
- 用
- 简化后续分组逻辑:在
$group阶段直接使用预处理好的packageText,避免嵌套的复杂表达式,提升可读性和稳定性。
内容的提问来源于stack exchange,提问作者solarenqu
相关产品推荐
相关产品推荐

