一、findDistinct去重
使用mongoTemplate.findDistinct
去重,不支持排序,即使你的query条件带sort排序方法。
-
优点:查询效率高。
-
缺点:只返回单一字段。不可多字段返回。不能使用排序,不推荐使用。
Query query = new Query();
query.addCriteria(Criteria.where("deviceId").is(getListParam.getDeviceId())).with(Sort.by(Sort.Order.desc("startDate")));
List list = mongoTemplate.find(query, RedPacketDeviceRelation.class);
List activeCodes = mongoTemplate.findDistinct(query, "activeCode", "redPacketDeviceRelation",RedPacketDeviceRelation.class, RedPacketDeviceRelation.class);
二、TypedAggregation去重
使用mongoTemplate.aggregate
去重,支持排序,推荐使用
-
优点:可指定返回类型。支持排序
-
缺点:排序是查询效率会变的非常低
TypedAggregation tagg = TypedAggregation.newAggregation(RedPacketDeviceRelation.class,
Arrays.asList(
//筛选条件
TypedAggregation.match(Criteria.where("deviceId").is(getListParam.getDeviceId())),
//分组过滤条件,first,as里最后包含展示的字段
TypedAggregation.group("activeCode").first("activeCode").as("activeCode").first("startDate").as("startDate"),
//挑选需要字段
TypedAggregation.project("activeCode", "startDate"),
//排序字段
TypedAggregation.sort(Sort.by(Sort.Order.desc("startDate")))
)
);
AggregationResults result111 = mongoTemplate.aggregate(tagg, RedPacketDeviceRelation.class);
List rd = result111.getMappedResults();
log.debug("排序后的mongoTemplate.group列表1:"+rd);
三、Aggregation去重
第三种,用法和第二种类似
Aggregation agg = Aggregation.newAggregation(
// 挑选所需的字段,类似select *,*所代表的字段内容
Aggregation.project("activeCode", "startDate","packetType"),
// sql where 语句筛选符合条件的记录
Aggregation.match(Criteria.where("deviceId").is(getListParam.getDeviceId())),
// 分组条件,设置分组字段
Aggregation.group("activeCode").first("activeCode").as("activeCode"),
// 排序(根据某字段排序 倒序)
Aggregation.sort(Sort.Direction.DESC,"startDate"),
// 重新挑选字段
Aggregation.project("activeCode")
);
AggregationResults results = mongoTemplate.aggregate(agg, "redPacketDeviceRelation", JSONObject.class);
List a= results.getMappedResults();
log.debug("排序后的code列表2:[{}]",results);
四、项目实践代码
4.1. 实现功能
SpringDataMongoDB去重+排序+分页
4.2 代码
1、Service代码
/**
* 获取用户评论过的动态
* 1、用户可以对同一动态评论多次,因此显示时要按动态id去重
* 2、新评论的动态显示在前面,因此要按评论时间倒序
* 3、需要分页显示
* @param pagerVO
* @param memberId
* @return
*/
private IPage<DynamicDetailDTO> pageMemberCommentDynamic(PagerVO pagerVO, Long memberId) {
List<AggregationOperation> operations = new ArrayList<>();
operations.add(MongoUtils.match("deleted", false));
operations.add(MongoUtils.match("memberId", memberId));
//分组前先按时间倒序
operations.add(Aggregation.sort(Sort.Direction.DESC, "createTime"));
//分组(去重) 使用mongoTemplate.findDistinct去重,不支持排序
operations.add(Aggregation.group("dynamicId").first("dynamicId").as("dynamicId").first("createTime").as("createTime"));
//分组后再按时间倒序一次
operations.add(Aggregation.sort(Sort.Direction.DESC, "createTime"));
//只取dynamicId字段
operations.add(Aggregation.project("dynamicId"));
//总数
Long totalCount = repositoryOps.getTotalCount(operations, "comment", DynamicIdVO.class);
//分页参数
operations.add(Aggregation.skip((long) pagerVO.getPageMG() * pagerVO.getLimit()));
operations.add(Aggregation.limit(pagerVO.getLimit()));
Aggregation aggregation = Aggregation.newAggregation(operations);
AggregationResults<DynamicIdVO> results = mongoTemplate.aggregate(aggregation, "comment", DynamicIdVO.class);
if(CollectionUtil.isEmpty(results.getMappedResults())){
return nullPageData(DynamicDetailDTO.class);
}
List<String> dynamicIdList = results.getMappedResults().stream().map(DynamicIdVO::getDynamicId).collect(Collectors.toList());
//通过动态ID集合去取详情列表
List<DynamicDetailDTO> detailDTOS = getDynamicDTOsByIds(dynamicIdList);
if (CollectionUtils.isEmpty(detailDTOS)) {
return nullPageData(DynamicDetailDTO.class);
}
return MongoUtils.getPage(pagerVO.getPage(), (long) detailDTOS.size(), totalCount, detailDTOS);
}
2、DynamicIdVO
@Data
public class DynamicIdVO {
private String dynamicId;
}
3、分页参数
@ApiModel(description = "分页参数")
public class PagerVO {
@ApiModelProperty(value = "页数", position = 1, dataType = "int", example = "1")
@BindQuery(ignore = true)
Integer page = 1;
@ApiModelProperty(value = "行数", position = 1, dataType = "int", example = "10")
@BindQuery(ignore = true)
Integer limit = 20;
@ApiModelProperty(value = "排序方式 升序:asc,降序:desc", position = 2)
@BindQuery(ignore = true)
SortTypeEnum sortType = SortTypeEnum.desc;
@ApiModelProperty(value = "排序字段", position = 3, example = "createTime")
@BindQuery(ignore = true)
String sort = "createTime";
@ApiModelProperty(value = "总数", position = 4,dataType = "int", example = "100")
Integer totalCount = 0;
public PagerVO(Long page, Long limit) {
this.page = (int) page.longValue();
this.limit = (int) limit.longValue();
}
public void setPage(Integer page) {
if (page == null || page == 0) {
// 如果不存在页数则置入1
this.page = 1;
} else {
// 存在则置入对应值
this.page = page;
}
}
@ApiModelProperty(hidden = true)
public Integer getPageMG() {
Integer page = this.getPage();
if (page > 0) {
return page -1;
}
return 0;
}
public void setLimit(Integer limit) {
if (limit == null) {
// 如果不存在行数则置入Integer最大值
this.limit = 20;
} else {
// 存在则置入对应值
this.limit = limit;
}
}
}
4、获取分页总记录数
public <T> Long getTotalCount (List<AggregationOperation> operations, String collectName, Class<T> outputType) {
long totalCount = 0;
if (!org.springframework.util.CollectionUtils.isEmpty(operations)) {
Aggregation aggregation = Aggregation.newAggregation(operations);
AggregationResults<T> comment = mongoTemplate.aggregate(aggregation, collectName, outputType);
totalCount = comment.getMappedResults().size();
} else {
List<T> all = mongoTemplate.findAll(outputType);
totalCount = all.size();
}
return totalCount;
}
5、MongoUtils.getPage
/**
* @param pageNum 当前页
* @param size 当前页行数
* @param total 总记录数
* @param data 实体数据
* @param <T>
* @return
*/
public static <T> IPage<T> getPage(int pageNum, Long size, Long total, List<T> data) {
IPage<T> page = new Page<>(pageNum, size, total);
page.setRecords(data);
return page;
}
4.3 补充
排除_id
operations.add(Aggregation.project("dynamicId").andExclude("_id"));
网友评论