【问题标题】:Is it possible to rename _id field after mongo's group aggregation?是否可以在 mongo 的组聚合后重命名 _id 字段?
【发布时间】: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 它在管道的下一个阶段

标签: java mongodb aggregation-framework rename


【解决方案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")))
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-11-22
            • 2013-01-05
            • 2016-08-16
            • 2016-05-17
            • 1970-01-01
            • 1970-01-01
            • 2013-06-11
            相关资源
            最近更新 更多