如何在Spring Data MongoDB中通过查找和过滤创建高级聚合?

问题描述

我需要使用具有以下模型的Spring Data MongoDB创建高级聚合:

@Getter
@Setter
@Document
public class Library {

  @Id
  @JsonSerialize(using = ToStringSerializer.class)
  private ObjectId id;

  private Address address;

  private String workingHours;

  ...

}

@Getter
@Setter
@Document
public class Book {

  @Id
  @JsonSerialize(using = ToStringSerializer.class)
  private ObjectId id;

  private Boolean published;

  private Boolean hidden;

  private String title;

  @DBRef
  @NotNull
  private Library library;

  ...

}

pom.xml

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
        <version>2.2.0</version>
</dependency>

图书馆藏书:

{ 
    "_id" : ObjectId("5f45440ee89590218e83a697"),"workingHours" : "8:00 PM - 8:00 AM","address" : DBRef("addresses",ObjectId("5f4544198da452a5523e3d11"))
}

图书收藏:

{ 
    "_id" : ObjectId("5f454423be823729015661ed"),"published": true,"hidden": false,"title": "The Hobbit,or There and Back Again"
    "library" : DBRef("libraries",ObjectId("5f45440ee89590218e83a697"))
},{ 
    "_id" : ObjectId("5f45445b876d08649b88ed5a"),"title": "Harry Potter and the Philosopher's Stone"
    "library" : DBRef("libraries",{ 
    "_id" : ObjectId("5f45446c7e33ca70363f629a"),"title": "Harry Potter and the Cursed Child"
    "library" : DBRef("libraries",{ 
    "_id" : ObjectId("5f45447285f9b3e4cb8739ad"),"title": "Fantastic Beasts and Where to Find Them"
    "library" : DBRef("libraries",{ 
    "_id" : ObjectId("5f45449fc121a20afa4fbb96"),"published": false,"title": "Universal Parks & Resorts"
    "library" : DBRef("libraries",{ 
    "_id" : ObjectId("5f4544a5f13839bbe89edb23"),"hidden": true,"title": "Ministry of Dawn"
    "library" : DBRef("libraries",ObjectId("5f45440ee89590218e83a697"))
}

功能:

  1. 用户必须能够按每个字段进行过滤。 ->那对我来说不是问题。根据传递的参数,我将创建Criteria并使用Aggregation.match()
  2. 根据用户的上下文,我必须返回可以基于startsWith()like()原则进行过滤的不同数量的图书。 ->这是个问题。

假设我有四本已出版的书,普通用户又添加了一本,隐藏的又一本。

  1. 管理员应该了解所有这些信息,因此他会将booksCount视为6
  2. 普通用户只能看到自己发布或添加的内容,因此他会将booksCount视为5
  3. 未登录的用户只会看到已发布的用户,因此他会将booksCount视为4
  4. 将来还会有其他情况。
Criteria criteria = Criteria.where("_id").ne(null).and("address.city").is("Chicago");

if (!isAdministrator()) {
    criteria = criteria.and("published").is(Boolean.TRUE);
}

MatchOperation matchOperation = Aggregation.match(criteria);

LookupOperation lookupOperation = LookupOperation.newLookup().from("books").localField("id").foreignField("library.$id").as("books");

UnwindOperation unwindOperation = Aggregation.unwind("books");
CountOperation countOperation = Aggregation.count().as("booksCount");

Aggregation aggregation = Aggregation.newAggregation(matchOperation,lookupOperation,unwindOperation,countOperation);

mongoTemplate.aggregate(aggregation,"libraries",Document.class).getRawResults().getInteger("booksCount");

起初我以为我会使用LookupOperation,但是它不能正常工作(它会独立于ObjectId来获取藏书中的所有书籍)。不幸的是,我遇到一个问题,除了在DBRef阶段,我们无法在聚合管道中使用$matchHere is the description of the problem

我阅读了第二篇文章中的解释,但是我不知道如何使用Spring Data MongoDB通过地图操作实现这种高级投影。此外,我希望能够按照第二点中的描述按此值进行过滤。

我的问题是:

  1. 如何使用Spring Data MongoDB实现这种行为(我也许可以稍微调整一下版本)?
  2. 如果我们执行此操作,是否可以按照说明中所述对booksCount应用适当的过滤器?
  3. 是否存在使用其他库,框架或功能来实现这种行为的另一种方法?我只考虑自定义DTO,查询所有现有库,遍历它们并基于传递的参数查询booksCount。但这并不能解决过滤和分页问题。

谢谢。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)