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

xtupzzrd  于 2023-04-05  发布在  Go
关注(0)|答案(7)|浏览(288)

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

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

我从Java中执行这个查询,我想将它Map到我的类上,但我不想将_idMap到name字段上。因为如果我这样做:

@JsonProperty("_id")
private String name;

然后,当我将此数据保存回mongo时(经过一些修改),数据以名称_id保存,而我希望生成一个真实的ID。
那么,$group操作后,如何重命名_id呢?

bz4sfanl

bz4sfanl1#

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

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

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

bqf10yzr

bqf10yzr2#

从mongo v3.4开始,你可以将$addFields$project结合使用,以避免在$project中写入所有字段,这可能会非常繁琐
$project中会发生这种情况,因为如果您特别包含一个字段,则其他字段将被自动排除。
示例:

{ 
  $addFields: { my_new_id_name: "$_id" }
},
{
  $project: { _id: 0 }
}
bfhwhh0e

bfhwhh0e3#

db.report.aggregate(   
{     
$group: {_id: '$name'} 
},
{
$project:{
  name:"$_id",
 _id:false} }
 )
osh3o9ms

osh3o9ms4#

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阶段从文档中删除/排除要重命名的字段。

vlju58qv

vlju58qv5#

如果你使用的是find方法,你不能这样做,但如果你使用的是aggregation,它是非常容易的,就像这样:

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

bbuxkriu6#

由于所有的答案都是在MongoDB查询中编写的解决方案,尽管问题在Java中寻求解决方案,但我使用Java的方法用于后期。
分组后,我们可以使用Projections.computed("<expected field name>", "$_id")))重命名_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<>());

为了具体地回答这个问题,我从上面的代码片段中摘录了一段代码,在这里我使用Projections.computed("name", "$_id")_id字段值重命名为name,它将分组后得到的_id的值Map到名为name的字段。此外,我们应该使用Projections.excludeId()排除id。

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

kyks70gy7#

以下是使用MongoTemplate的Java工作示例:

GroupOperation groupByMovie = Aggregation.group("movieId")
                .avg("rating").as("averageRating");

        SortOperation sortByAvgRatingDesc = Aggregation.sort(Sort.Direction.DESC, "averageRating");
        LimitOperation limitRows = Aggregation.limit(limit);
        ProjectionOperation projectionOperation = Aggregation.project()
                .and("_id").as("movieId")
                .and("averageRating").as("averageRating")
                .andExclude("_id");

        Aggregation aggregation = Aggregation.newAggregation(
                groupByMovie,
                projectionOperation,
                sortByAvgRatingDesc,
                limitRows
        );

        AggregationResults<TopRatedMovie> results = mongoTemplate.aggregate(aggregation, MovieRating.class, TopRatedMovie.class);

        return results.getMappedResults();

相关问题