在Spring Data Mongodb中使用$$ ROOT来检索整个文档

Che*_*man 0 java mongodb spring-data aggregation-framework

使用mongodb shell,我能够执行一个检索整个文档的聚合查询.为了做到这一点,我使用$$ ROOT变量.

db.reservations.aggregate([
   { $match : { hotelCode : "0360" } },
   { $sort : { confirmationNumber : -1 , timestamp: -1 } },
   { $group : {
       _id : "$confirmationNumber",
       timestamp :{$first : "$timestamp"},
       fullDocument :{$first : "$$ROOT"}
   }}
])
Run Code Online (Sandbox Code Playgroud)

它检索内容为confirmationNumber,timestamp,fullDocument的对象.fullDocument是整个文档.

我想知道是否可以对Spring-Data和聚合框架做同样的事情.

我的java代码是:

TypedAggregation<ReservationImage> aggregation = newAggregation(
   ReservationImage.class,
   match(where("hotelCode").is(hotelCode)),
   sort(Direction.DESC,"confirmationNumber","timestamp"),
   group("confirmationNumber").
     first("timestamp").as("timestamp").
     first("$$ROOT").as("reservationImage"));
  List<myClass> items = mongoTemplate.aggregate(
    aggregation, 
    myClass.class).getMappedResults();
Run Code Online (Sandbox Code Playgroud)

错误是:org.springframework.data.mapping.PropertyReferenceException:找不到类型myClass的属性$$

你有什么想法?

谢谢.

Tho*_*ont 6

我们创建了https://jira.spring.io/browse/DATAMONGO-954来跟踪从MongoDB Pipeline表达式访问系统变量的支持.

一旦到位,您应该能够写:

Aggregation agg = newAggregation( //
   match(where("hotelCode").is("0360")), //
   sort(Direction.DESC, "confirmationNumber", "timestamp"), //
   group("confirmationNumber") //
      .first("timestamp").as("timestamp") //                
      .first(Aggregation.ROOT).as("reservationImage") //
);
Run Code Online (Sandbox Code Playgroud)


Nei*_*unn 5

我以前见过这种事情,它不仅仅限于变量名称,例如$$ROOT. Spring data 对于如何在管道中映射文档的“属性”有自己的想法。另一个常见问题是简单地投影一个新的或计算的字段,该字段本质上具有一个无法识别的新“属性”名称。

也许最好的方法是“放弃”使用辅助类和方法,并将管道构建为 BSON 文档。您甚至可以获取底层集合对象和原始输出作为 BSON 文档,但最后仍然转换为您类型化的 List。

里程可能会因您的实际方法而异,但本质上是:

    DBObject match = new BasicDBObject(
        "$match", new BasicDBObject(
            "hotelCode", "0360"
        )
    );

    DBObject sort = new BasicDBObject(
        "$sort", new BasicDBObject(
        "cofirmationNumber", -1
        ).append("timestamp", -1)
    );

    DBObject group =  new BasicDBObject(
        "$group", new BasicDBObject(
            "_id", "confirmationNumber"
        ).append(
            "timestamp", new BasicDBObject(
                "$first", "$timestamp"
            )
        ).append(
            "reservationImage", new BasicDBObject(
                "$first", "$$ROOT"
            )
        )
    );

    List<DBObject> pipeline = Arrays.asList(match,sort,group);

    DBCollection collection = mongoOperation.getCollection("collection");
    DBObject rawoutput = (DBObject)collection.aggregate(pipeline);

    List<myClass> items = new AggregationResults(List<myClass>, rawoutput).getMappedResults();
Run Code Online (Sandbox Code Playgroud)

最重要的是远离那些阻碍的帮助者并建造管道,因为它应该不受强加的限制。