SpringDataMongoDB去重+排序+分页

一、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"));
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容