MongoDB聚合$group后添加ObjectId类型_id字段的实现疑问
MongoDB聚合结果添加ObjectId类型_id字段(源集合无_id场景)
场景背景
现有regions集合文档(示例):
{ region: "US", name: "United State" }, { region: "US", name: "United State" }
执行原聚合命令后得到无_id字段的结果:
db.regions.aggregate([ {$group: {_id: {region: "$region", name: "$name"}, priority: {$sum: 1}}}, {$project: { code: "$_id.region", name: "$_id.name", priority: "$priority"} ])
返回结果:
{ "code" : "US", "name" : "United State", "priority" : 2}
需求:生成包含ObjectId类型_id字段的聚合结果,以便用$out输出到新集合,目标格式:
{ "code" : "US", "name" : "United State", "priority" : 2, _id: ObjectId("xxxxxxxxxxx")}
已实现的源集合含_id时的方案(参考@Gibbs提示):
db.collection.aggregate([ { $group: { "id": { $push: "$_id" }, _id: { region: "$region", name: "$name" }, priority: { $sum: 1 } } }, { $project: { code: "$_id.region", name: "$_id.name", priority: "$priority", _id: { $first: "$id" } } } ])
核心问题
若源集合本身不包含_id字段,如何在聚合结果中添加ObjectId类型的_id字段?
解决方案
利用MongoDB 4.4+版本支持的$function操作符,在聚合的$project阶段生成新的ObjectId:
方案代码示例
db.regions.aggregate([ { $group: { _id: { region: "$region", name: "$name" }, priority: { $sum: 1 } } }, { $project: { code: "$_id.region", name: "$_id.name", priority: "$priority", _id: { $function: { body: function() { return new ObjectId(); }, args: [], lang: "js" } } } }, { $out: "target_collection" } // 将结果输出到目标集合 ])
说明
$function允许在聚合中调用JavaScript函数,这里通过new ObjectId()生成唯一的ObjectId值- 该方法要求MongoDB版本≥4.4;如果是更低版本,可在聚合后通过客户端代码生成ObjectId再插入目标集合
- 生成的ObjectId具备MongoDB主键的唯一性特性,适合作为输出集合的
_id字段
内容的提问来源于stack exchange,提问作者Ch Etang
相关产品推荐
相关产品推荐

