[英]How can i get unique count aggregation by field value with Spring Data?
[英]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.