如何在 Spring Boot with MangoDB 中使用聚合和条件获取包含字段计数的数据列表

How to get list of data containing count of a field using Aggregation and Criteria in Spring Boot with MangoDB

要求: documents-bookdata 集合可能有多个 bookPublisherName 相同但 bookName 不同的对象。意味着多本书可以有相同的出版商,因此需要提取每个出版商的图书数量。

型号class:

@Document(collection = "documents-bookdata")
public class DocumentsBookdata {

    @Id
    private String bookId;
    private String bookName;
    private String bookPublisherName;
//setters and getters
}

响应格式pojo

public class PublisherBookCount {

private String bookPublisherName;
private int bookCount;
//setters and getters
}

响应格式

 [
 { "bookPublisherName": "docClassA", "bookCount": 3023 },
 { "bookPublisherName": "docClassB", "bookCount": 4100 }
 ]

您可以为 Group by 实现 Utility class,如下所示。

public class GroupByUtility<T> implements Consumer<T> {
    public static <T extends Comparable<? super T>> Collector<T, ?, GroupByUtility<T>>
    statistics() {
        return statistics(Comparator.<T>naturalOrder());
    }

    public static <T> Collector<T, ?, GroupByUtility<T>>
    statistics(Comparator<T> comparator) {
        Objects.requireNonNull(comparator);
        return Collector.of(() -> new GroupByUtility<>(comparator),
                GroupByUtility::accept, GroupByUtility::merge);
    }

    private final Comparator<T> c;
    private T min, max;
    private long count;

    public GroupByUtility(Comparator<T> comparator) {
        c = Objects.requireNonNull(comparator);
    }

    public void accept(T t) {
        if (count == 0) {
            count = 1;
            min = t;
            max = t;
        } else {
            if (c.compare(min, t) > 0) min = t;
            if (c.compare(max, t) < 0) max = t;
            count++;
        }
    }

    public GroupByUtility<T> merge(GroupByUtility<T> s) {
        if (s.count > 0) {
            if (count == 0) {
                count = s.count;
                min = s.min;
                max = s.max;
            } else {
                if (c.compare(min, s.min) > 0) min = s.min;
                if (c.compare(max, s.max) < 0) max = s.max;
                count += s.count;
            }
        }
        return this;
    }

    public long getCount() {
        return count;
    }

    public T getMin() {
        return min;
    }

    public T getMax() {
        return max;
    }

}

然后从您的代码中调用该实用程序 class 方法以按字段指定为组

获取 Count,Min and Max
        List<DocumentsBookdata> documentsBookdata=new ArrayList();
        Map<Long, GroupByUtility<DocumentsBookdata>> maxMap = documentsBookdata.stream()
                .collect(Collectors.groupingBy(o -> o.getBookId(),
                        GroupByUtility.statistics(Comparator.comparing(o -> o.getPublisherName()))));
        return maxMap.entrySet().stream().map(obj->obj.getValue().getCount()).collect(Collectors.toList());

这个要求也可以在逻辑上完成..比如使用 findAll 获取 DocumentsBookdata 列表,然后使用循环过滤它并存储每个 publisher.But 的书籍数量,这将是一个冗长的 approach.SO下面的代码将简单地使用聚合来获取每个出版商的图书数量

public List<PublisherBookCount> getBookCOunt(){
    List<PendingDocumentCount> list = new ArrayList<>();
    PublisherBookCount count = null;
    Aggregation aggregation = Aggregation.newAggregation( Aggregation.project("bookPublisherName").andExclude("_id"),
                                                                   Aggregation.sortByCount("bookPublisherName"));
    List<Document> docs=  mongoTemplate.aggregate(aggregation, "documents-bookdata", Document.class).getMappedResults();
          for(Document doc : docs) {
          count = new PublisherBookCount();
              count.setBookPublisherName(doc.get("bookPublisherName").toString());
              count.setBookCount(Integer.parseInt(doc.get("count").toString()));
              list.add(count);
          }
          
          return list;
      }