簡體   English   中英

如何在 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 不同的對象。 意味着多本書可以有相同的出版商,因此需要提取每個出版商的圖書數量。

Model 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 }
 ]

這個要求也可以在邏輯上完成。比如使用 findAll 獲取 DocumentsBookdata 列表,然后使用循環過濾它並存儲每個出版商的書籍數量。但這將是一個冗長的方法。所以下面的代碼將簡單地使用聚合來獲取每個出版商的圖書數量

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;
      }

您可以按以下方式為Group by實施實用程序 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());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM