title: Spring Data MongoDB Aggregation - rename _id in projection
body: <p>In the mongo (3.6) shell I can execute the following aggregation to project and rename &quot;_id&quot; to something else:</p>
  <pre><code>db.collection.aggregate([
    { $group : { _id : ... },
    { $project : {   '_id': 0,        // exclude the id field
                     'name' : '$_id', // project the &quot;old&quot; id value to the &quot;name&quot; field
                     ...
                 }
    }
  ])
  </code></pre>
  <p>I need to translate this using spring-data-mongo (via Spring Boot 2.3.1).
  I can exclude the id field with the following ProjectionOperation:</p>
  <pre><code>project().andExclude(&quot;_id&quot;)
  </code></pre>
  <p>But so far I've been unabled to rename the id field.
  None of the following works:</p>
  <ul>
  <li><p>my first guess</p>
  <pre><code>  project().and(&quot;_id&quot;).as(&quot;name&quot;)
  </code></pre>
  </li>
  <li><p>as suggested <a href="https://www.baeldung.com/spring-data-mongodb-projections-aggregations#2-get-smallest-state-by-average-city-population" rel="nofollow noreferrer">here</a></p>
  <pre><code>  project().andExpression(&quot;_id&quot;).as(&quot;name&quot;) 
  </code></pre>
  </li>
  </ul>
  <p>It shouldn't be that hard, but I can't figure out what I'm missing.</p>
  <hr />
  <p>EDIT: data sample and full aggregation pipeline to reproduce failure</p>
  <p>With the following documents:</p>
  <pre><code>{ 
      &quot;_id&quot; : ObjectId(&quot;5a0c7a3135587511c9247db4&quot;), 
      &quot;_class&quot; : &quot;task&quot;, 
      &quot;category&quot; : &quot;green&quot;, 
      &quot;status&quot; : &quot;OK&quot;
  }
  { 
      &quot;_id&quot; : ObjectId(&quot;5a0cd21d35587511c9247db8&quot;), 
      &quot;_class&quot; : &quot;task&quot;, 
      &quot;category&quot; : &quot;red&quot;, 
      &quot;status&quot; : &quot;KO&quot;
  }
  </code></pre>
  <p>Domain object:</p>
  <pre><code>@Document(collection = &quot;tasks&quot;)
  @TypeAlias(&quot;task&quot;)
  public class Task {
  
      @Id
      private String id;
      private String status;
      private String category;
  
      // getters/setters omitted
  }
  </code></pre>
  <p>And the following aggregation:</p>
  <pre><code>Aggregation a = Aggregation.newAggregation(
                  group(&quot;status&quot;, &quot;category&quot;).count().as(&quot;count&quot;),
                  group(&quot;_id.category&quot;).push(
                          new Document(&quot;k&quot;, &quot;$_id.status&quot;).append(&quot;v&quot;, &quot;$count&quot;))
                          .as(&quot;counts&quot;),
                  project().and(arrayToObject(&quot;$counts&quot;)).as(&quot;counts&quot;),
                  // this final stage fails with: a java.lang.IllegalArgumentException: Invalid reference '_id'!
                  project().and(&quot;_id&quot;).as(&quot;name&quot;).andExclude(&quot;_id&quot;)
          );
  
  mongotemplate.aggregate(a, &quot;tasks&quot;, org.bson.Document.class)
  </code></pre>
  <p>Before the last pipeline stage, the aggregation gives :</p>
  <pre><code>[ { &quot;_id&quot; : &quot;green&quot;, &quot;counts&quot; : { &quot;OK&quot; : 1 } },
    { &quot;_id&quot; : &quot;red&quot;, &quot;counts&quot; : { &quot;KO&quot; : 1 } } ]
  </code></pre>
  <p>So we should able to project &quot;_id&quot; to &quot;name&quot;, but instead we get this:</p>
  <pre><code>java.lang.IllegalArgumentException: Invalid reference '_id'!
      at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:114) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:77) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.aggregation.ProjectionOperation$ProjectionOperationBuilder$FieldProjection.renderFieldValue(ProjectionOperation.java:1445) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.aggregation.ProjectionOperation$ProjectionOperationBuilder$FieldProjection.toDocument(ProjectionOperation.java:1432) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.aggregation.ProjectionOperation.toDocument(ProjectionOperation.java:261) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.aggregation.AggregationOperation.toPipelineStages(AggregationOperation.java:55) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.aggregation.AggregationOperationRenderer.toDocument(AggregationOperationRenderer.java:56) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.aggregation.Aggregation.toPipeline(Aggregation.java:721) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.AggregationUtil.createPipeline(AggregationUtil.java:95) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.MongoTemplate.doAggregate(MongoTemplate.java:2118) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:2093) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
      at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1992) ~[spring-data-mongodb-3.0.1.RELEASE.jar:3.0.1.RELEASE]
  </code></pre>
  <p>I already found a workaround (see below), but I'm still curious why the aggregation shown above fails. I don't get why the &quot;_id&quot; reference is not exposed properly.</p>
  <p>The successful workaround:</p>
  <pre><code>Aggregation a = Aggregation.newAggregation(
              group(&quot;status&quot;, &quot;category&quot;).count().as(&quot;count&quot;),
              group(&quot;_id.category&quot;).push(
                      new Document(&quot;k&quot;, &quot;$_id.status&quot;).append(&quot;v&quot;, &quot;$count&quot;))
                      .as(&quot;counts&quot;),
              project().and(arrayToObject(&quot;$counts&quot;)).as(&quot;counts&quot;),
              // the following works
              addFields().addFieldWithValue(&quot;name&quot;, &quot;$_id&quot;).build(),
              project().andExclude(&quot;_id&quot;).andExclude(&quot;counts&quot;)
      );
  </code></pre>
  <hr />
  <p>For anyone needing a workaround when they can't figure out who to convert a MongoDB aggregation to a Spring Data Mongo aggregation: <a href="https://stackoverflow.com/a/59726492/5873923">https://stackoverflow.com/a/59726492/5873923</a></p>