美文网首页spring
SpringDataMongoDB去重+排序+分页

SpringDataMongoDB去重+排序+分页

作者: AC编程 | 来源:发表于2022-04-26 16:12 被阅读0次

一、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"));

相关文章

网友评论

    本文标题:SpringDataMongoDB去重+排序+分页

    本文链接:https://www.haomeiwen.com/subject/pyfhyrtx.html