是否可以在 mongo 的组聚合后重命名 _id 字段?

Posted

技术标签:

【中文标题】是否可以在 mongo 的组聚合后重命名 _id 字段?【英文标题】:Is it possible to rename _id field after mongo's group aggregation? 【发布时间】:2017-09-18 04:11:57 【问题描述】:

我有一个这样的查询(简化):

db.collection.aggregate([
   $match:  main_id: ObjectId("58f0f67f50c6af16709fd2c7")  , 
  
    $group: 
      _id: "$name",
      count:  $sum: 1 ,
      sum:  $sum:  $add: ["$P31", "$P32"]  
    
  
])

我从 Java 执行此查询,我想将它映射到我的班级,但我不希望将 _id 映射到 name 字段。因为如果我这样做:

@JsonProperty("_id")
private String name;

然后,当我将此数据保存回 mongo(经过一些修改)时,数据以名称保存为 _id,而我希望生成一个真实的 Id。

那么,我如何在$group 操作之后重命名 _id

【问题讨论】:

$project 它在管道的下一个阶段 【参考方案1】:

您可以通过在管道末尾添加$project 阶段来实现这一点,如下所示:

 $project:   
      _id: 0,
      name: "$_id",
      count: 1,
      sum: 1
   

在线试用:mongoplayground.net/p/QpVyh-0I-bP

【讨论】:

【参考方案2】:

从 mongo v3.4 开始,您可以将$addFields$project 结合使用,以避免在$project 中写入可能非常乏味的所有字段。

这发生在$project 中,因为如果您专门包含一个字段,其他字段将被自动排除。

例子:

 
  $addFields:  my_new_id_name: "$_id" 
,

  $project:  _id: 0 

【讨论】:

对我不起作用,我得到$projection requires at least one output field.(在聚合中使用它) 澄清:我在 AWS 中使用 DocumentDB 它工作正常,但我需要将_id转换为字符串,所以 $addFields: id: $toString: '$_id' 和管道的顺序应该得到尊重,首先$addFields$project【参考方案3】:
 db.report.aggregate(   
     
$group: _id: '$name' 
,

$project:
  name:"$_id",
 _id:false 
 )

【讨论】:

【参考方案4】:

如果你使用find 方法你不能这样做,但如果你使用aggregation 这很简单:

db.collectionName.aggregate([
    
        $project: 
            newName: "$existingKeyName"
        
    
]);

【讨论】:

【参考方案5】:

Mongo 4.2 开始,您可以使用$set / $unset 阶段的组合:

//  x: 1, z: "a" 
//  x: 2, z: "b" 
db.collection.aggregate([
   $set:  y: "$x"  ,
   $unset: "x" 
])
//  y: 1, z: "a" 
//  y: 2, z: "b" 

$set 阶段将新字段添加到文档中,$unset 阶段从文档中删除/排除要重命名的字段。

【讨论】:

【参考方案6】:

由于所有答案都是在 MongoDB 查询中编写的解决方案,尽管该问题在 Java 中寻求解决方案,因此将我使用 Java 的方法发布给后代。

分组后,我们可以使用重命名_id 字段名 Projections.computed("<expected field name>", "$_id")))

将问题中提到的查询的核心部分转换为Java

        Bson mainIdMatch = match(eq("main_id", new ObjectId("58f0f67f50c6af16709fd2c7")));
        Bson group = Aggregates.group("$name", Accumulators.sum("count", 1L));
        Bson project = Aggregates.project(Projections.fields(Projections.excludeId(),
                Projections.computed("name", "$_id")));
        reportMongoCollection.aggregate(Arrays.asList(mainIdMatch, group, project))
                .into(new ArrayList<>());

为了具体回答,我添加了上述代码 sn-p 的摘录,其中我使用 Projections.computed("name", "$_id")_id 字段值重命名为名称,它映射了我们得到的 _id 的值分组到名为name 的字段。此外,我们应该使用 Projections.excludeId() 排除 id。

Aggregates.project(Projections.fields(Projections.excludeId(),
                Projections.computed("name", "$_id")))

【讨论】:

以上是关于是否可以在 mongo 的组聚合后重命名 _id 字段?的主要内容,如果未能解决你的问题,请参考以下文章

Mongo 聚合计数子文档(计数回复评论)

mongodb Aggregation聚合操作之$bucket

运行查询时,mongo上的聚合函数运行速度非常慢

如何在mongo聚合不起作用的情况下将字符串转换为日期总是返回null?

Mongo 逐对聚合

获取空值,$sum 聚合 - Mongo