Spring Data MongoDB Aggregation涉及Unwind,Match,Sort& Group

时间:2017-08-20 04:14:12

标签: spring mongodb spring-data spring-data-mongodb

我有一个名为用户的集合,其中包含名为消息的嵌入式文档。嵌入式文档消息包含消息对象的数组,如下所示:

{
  "_id" : ObjectId("58e09daa192216e39fd85433"),
  "userId" : "user123",
  "message" : [ 
    {
        "messageId" : "5277941e-9d84-46c3-b927-ef33abbf35f2",
        "dateCreated" : 1491115000,
        "body" : "howdy?",
        "type" : "text"
    }, 
    {
        "messageId" : "c2ce0480-bc0d-4393-89d4-27174d323b98",
        "dateCreated" : 1491119000,
        "body" : "i've problem with my account. can you help?",
        "type" : "text"
    }, 
    {
        "messageId" : "45b2593c-a960-4066-8723-db2531dd8bab",
        "dateCreated" : 1491100000,
        "body" : "this is urgent",
        "type" : "text"
    }
  ]
}

我的目标是根据 dateCreated 键对嵌入式文档消息进行排序。我需要将这个mongo查询转换为Spring Data MongoDB:

db.user.aggregate(
  {$unwind: "$message"}, 
  {$match: {userId: "user123"}},
  {$sort: {"message.dateCreated": 1}},
  {$group: {_id: "$_id", "message": {"$push": "$message"}}})

我已尝试以下代码,但仍然收到错误:

AggregationOperation unwind = Aggregation.unwind("message");
AggregationOperation match = Aggregation.match(Criteria.where("userId").in("user123"));
AggregationOperation sort = Aggregation.sort(Direction.ASC, "message.dateCreated");
AggregationOperation group = Aggregation.group("userId", "message");

Aggregation aggregation = Aggregation.newAggregation(unwind, match, sort, group);

AggregationResults<User> groupResults = mongoTemplate.aggregate(aggregation, User.class, User.class);

错误:

  

无法实例化[java.util.List]:指定的类是一个接口

用户类:

@Document(collection="user")
public class User {

  @Id
  private String id;
  private String userId;
  @Field("message")
  @DBRef
  private List<Message> message;
  //constructor, getter, setter
}

消息类:

@Document
public class Message {
  private String messageId;
  private long dateCreated;
  private String body;
  private String type;
  //constructor, getter, setter
}

提示:

根据我的研究,我非常确定我需要使用 GroupOperationBuilder group =  Aggregation.group(&#34; userId&#34;)。推(&#34;消息&#34;)但我真的不知道如何继续这样做,因为AggregationResults不允许我在 mongoTemplate.aggregate()

中使用它

2 个答案:

答案 0 :(得分:0)

优化查询将是:

db.user.aggregate(
 {$match: {userId: "user123"}},
 {$unwind: "$message"}, 
 {$sort: {"message.dateCreated": 1}},
 {$group: {_id: "$_id", "message": {"$push": "$message"}}});

如果您首先使用此给定查询,它将过滤符合您条件的文档,然后它将展开已过滤的文档。

答案 1 :(得分:0)

您的实体类似乎是错误的。为什么Message有@DBRef作为注释?

在我看来应该是这样的:

@Document(collection="user")
public class User {

  @Id
  private String id;
  private String userId;
  @Field("message")
  private List<Message> message;
  //constructor, getter, setter
}

public class Message {
  private String messageId;
  private long dateCreated;
  private String body;
  private String type;
  //constructor, getter, setter
}