【问题标题】:Spring Data MongoDB Aggregation involve Unwind,Match,Sort &GroupSpring Data MongoDB Aggregation 涉及 Unwind,Match,Sort &Group
【发布时间】:2017-08-20 04:14:12
【问题描述】:

我有一个名为 User 的集合,其中包含名为 Message 的嵌入文档。嵌入文档 Message 包含 message 对象 数组,如下所示:

{
  "_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 键对嵌入文档 Message 进行排序。我需要将此 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("userId").push("message") 但我真的不知道该怎么做,因为 AggregationResults 不允许我在 mongoTemplate.aggregate() 中使用它

【问题讨论】:

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


    【解决方案1】:

    优化查询将是:

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

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

    【讨论】:

      【解决方案2】:

      您的实体类似乎是错误的。为什么 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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-06
        • 1970-01-01
        • 2017-07-04
        • 1970-01-01
        • 1970-01-01
        • 2017-08-06
        • 2015-12-17
        • 2021-05-15
        相关资源
        最近更新 更多