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

时间:2014-06-12 13:41:51

标签: 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"}
   }}
])

它检索内容为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();

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

你有什么想法吗?

感谢。

2 个答案:

答案 0 :(得分:6)

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

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

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

答案 1 :(得分:4)

我以前见过这种事情,它不仅限于$$ROOT之类的变量名。 Spring数据有自己的想法,如何映射&#34;属性&#34;管道中的文件。另一个常见问题是简单地投射一个新的或计算的字段,该字段基本上具有新的&#34;属性&#34;它的名称无法识别。

最好的方法可能是“退出”&#34;从使用辅助类和方法并构造管道作为BSON文档。您甚至可以将底层集合对象和原始输出作为BSON文档获取,但最后仍然会转换为您键入的列表。

里程可能与您的实际方法不同,但基本上是:

    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();

主要的是远离正在阻碍并构建管道的帮助者,因为它应该没有强加的限制。