在Spring Data MongoDB中按内部数组进行聚合和排序

问题描述

我对mongoDB很陌生。请忍受我。

我有一个名为Users的集合,其中包含角色列表。一个用户可以有多个角色,因此角色在一个数组中列出。我想按用户的角色名称对其进行排序。

用户结构如下,

{
  "_id": ObjectId("5bc910a39e53b62c7d4c4e62"),"_class": "User","userName": "John","fullName": "Doe","roles": [
    DBRef("roles",ObjectId("5d5cf8ceb3773255b54d18c6")),DBRef("roles",ObjectId("5d5cf8ceb3773255b54d18c7"))
  ]
}

课程

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

    @Id
    private String id;
    private String username;
    private String fullName;
    private boolean active;
    @DBRef
    private List<Role> roles;
  //constructor,getter,setter
}



@Document(collection = "roles")
public class Role {
    @Id
    private String id;
    private String name;

//constructor,setter

}

我尝试了以下方法

 Criteria criteria = new Criteria();
 setCriteriaReadOnlyIsNullOrReadOnlyIsFalse(criteria);
 criteria.andOperator(Criteria.where("<condition>").is(<"condition_data">));

 Aggregationoperation userMatch = Aggregation.match(criteria);
 LookupOperation lookupOperation = LookupOperation.newLookup()
                .from("roles")
                .localField("roles.id")
                .foreignField("id")
                .as("rolesAgg");
 Aggregationoperation sort = Aggregation.sort(Sort.Direction.DESC,"rolesAgg.name");
 Aggregationoperation project = Aggregation.project("id","userName","fullName","roles");


TypedAggregation<User> aggregation = newAggregation(User.class,userMatch,lookupOperation,sort,project);

return mongoOperations.aggregate(aggregation,User.class).getMappedResults();

这会产生结果,但由于 rolesAgg 是一组对象而无法排序。这是roleAgg每位用户显示的方式。

"rolesAgg": [
  {
    "_id": ObjectId("5d5cf8ceb3773255b54d18c3"),"name": "Super Admin"
  },{
    "_id": ObjectId("5d5cf8ceb3773255b54d18c5"),"name": "Customer Service"
  },{
    "_id": ObjectId("5d5cf8ceb3773255b54d18c4"),"name": "Admin"
  }
]

是否可以将 rolesAgg.name 提取到数组中,并使用该数组进行排序?我被卡住了。预先感谢您的帮助。

解决方法

对象在数组内部时无法排序。

[
  {
    "$unwind": "$rolesAgg"
  },{
    "$sort": {
      "rolesAgg.name": -1
    }
  },{
    $group: {
      _id: "$_id",username: {
        "$first": "$username"
      },"fullname": {
        "$first": "$fullname"
      },rolesAgg: {
        $push: "$rolesAgg"
      }
    }
  }
]

所以你需要做

使数组平坦

Aggregation.unwind("$rolesAgg")

按名称排序

Aggregation.sort(Sort.Direction.DESC,"rolesAgg.name")

要全部归组

Aggregation.group("_id)
    .first("username").as("username")
    .first("fullname").as("fullname")
    .push("rolesAgg").as("rolesAgg")

分别。

注意:如果您在分组时有更多字段,也请考虑

工作Mongo playground