MongoTemplate笔记---记录一次MongoDb的关联查询

基本用法

    /**
     * 分页查询所有idea信息,按点赞数排序
     * @param page
     * @param size
     * @param appVersion 查询的模式,当前版本,投票中
     * @return
     */
    @Override
    public List<UserIdea> userIdeaFindPage(Integer page, Integer size, Integer appVersion) {
        // 先在topicLike中查所有类型为1的,点赞数排行的分页数据(这里只查idea的点赞排行)

        // idea关联like
        LookupOperation idea = LookupOperation.newLookup()
                // 这里是次表的名称[主表是你下面执行查询所写的哪个表]
                .from("ad_user_idea")
                // 这里是主表打算用哪个字段来和上面那个次表进行关联
                .localField("topicOid")
                // 这里是次表用来和主表进行关联的字段
                .foreignField("_id")
                // 这样他们就有了一个临时表,给他取个别名
                .as("idea");

        // 点赞表筛选
        Criteria criteria = new Criteria();
        criteria.andOperator(
                // 这里是在主表执行的筛选条件
                Criteria.where("type").is(TopicLikeTypeEnum.IDEA_LIKE.getType()),
                Criteria.where("appVersion").is(appVersion),
                // 这里就用上面的别名idea.status指定关联临时表中的字段筛选关系
                Criteria.where("idea.status").is(1)
                );

        // 拼装查询条件
        Aggregation aggregation = Aggregation.newAggregation(
                // 关联临时表
                idea,
                // 添加筛选流程
                Aggregation.match(criteria),
                // 添加分组规则,这里使用count统计次数,赋予别名likeCount
                Aggregation.group("topicOid").count().as("likeCount"),
                // 添加排序规则,[注意这里由于处理器使用在分组后,刚好需要按照分组统计后AS的别名进行排序,所以这里的排序字段一定要和AS对应]
                Aggregation.sort(new Sort(Sort.Direction.DESC, "likeCount")),
                // 进行分页配置
                Aggregation.skip(Long.valueOf((page - 1) * size)),
                Aggregation.limit(size)
        );
        // 执行管道查询,,,注意这里参数中的第二个为collectionName,也就是集合名称,对应mongodb中的表名(管道,集合名称[主表],接收结果的结果集)
        AggregationResults<TopicLikeSortCount> ideaCount = mongoTemplate.aggregate(aggregation, "ad_topic_like", TopicLikeSortCount.class);
        // 这里和上一条的泛型字段一定要包含id和我们使用的AS likeCount否则无法封装
        List<TopicLikeSortCount> list = ideaCount.getMappedResults();
        for (Object topicLikeSortCount : list) {
            System.out.println(topicLikeSortCount);
        }
        // 提取出排行榜中的topicId,


        return null;
    }

几个比较坑的地方:

// idea关联like
LookupOperation idea = LookupOperation.newLookup()
        // 这里是次表的名称[主表是你下面执行查询所写的哪个表]
        .from("ad_user_idea")
        // 这里是主表打算用哪个字段来和上面那个次表进行关联
        .localField("topicOid")
        // 这里是次表用来和主表进行关联的字段
        .foreignField("_id")
        // 这样他们就有了一个临时表,给他取个别名
        .as("idea");

千万不要搞错了主表次表关联建的设置,一直以为local是本地的意思。就是当前表。。那我就很自然的用了上面from中指定的表的外键。谁知到它这个local代表的是主表;也就是当前操作表的意思,,

在就是如果表字段在合并以后有重复记得加上表名.字段

一些日常使用

查询话题最近评论的三个用户的id

String strobjectId = "618b2ffbfd780000010038ab";
        ObjectId objectId = new ObjectId(strobjectId);
        // 注意:这里是需要显示最近回复的三个用户,不是最近的三条回复的用户,否则会导致有用户连续回复的时候只显示一个用户
        Criteria criteria = new Criteria();
        criteria.andOperator(Criteria.where("parentCommentId").is(objectId));
        Aggregation aggregation = Aggregation.newAggregation(
                // 筛选id对应的
                Aggregation.match(criteria),
                Aggregation.sort(Sort.by(Sort.Order.desc("created"))),
                Aggregation.group("commentUserId"),
                Aggregation.limit(3)
        );
        AggregationResults<TreeMap> aggregate = mongoTemplate.aggregate(
                aggregation,
                UserIdeaComment.class,
                TreeMap.class
        );
        List<TreeMap> mappedResults = aggregate.getMappedResults();
        List<Long> ids = mappedResults.stream().map(tm -> Long.valueOf(tm.get("_id").toString())).collect(Collectors.toList());
        System.out.println(mappedResults);
        System.out.println("ids:" + ids);

查询上次结算以后参与投票并进入前十的总人数

public Long countVotedUserAmount(Integer appVersion) {
    LookupOperation idea = LookupOperation.newLookup()
            .from("ad_user_idea")
            .localField("topicOid")
            .foreignField("_id")
            .as("idea");
    Criteria criteria = new Criteria();
    criteria.andOperator(
            Criteria.where("idea.appVersion").is(appVersion),
            Criteria.where("likeType").is(TopicLikeTypeEnum.IDEA_LIKE.getType())
    );
    Aggregation aggregation = Aggregation.newAggregation(
            idea,
            Aggregation.match(criteria),
            Aggregation.group("topicOid").count().as("likeCount"),
            Aggregation.sort(Sort.by(Sort.Order.desc("likeCount"))),
            Aggregation.limit(10),
            Aggregation.count().as("userCount")
    );
    AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, TopicLike.class, Map.class);
    List<Map> mappedResults = aggregate.getMappedResults();
    Long userCount = Long.valueOf(mappedResults.get(0).get("userCount").toString());
    return userCount;
}

统计评论这个用户的用户,并且按照vip等级分组统计数量

public void test() {
    Long userId = 556L;
    LookupOperation hasVip = LookupOperation.newLookup()
            // 关联
            .from("ad_user_vip_syn_mongo")
            // 主表键
            .localField("sendUserId")
            // 关联表键
            .foreignField("userId")
            .as("hasVip");
    Criteria criteria = new Criteria();
    criteria.andOperator(Criteria.where("recUserId").is(userId));
    Aggregation aggregation = Aggregation.newAggregation(
            hasVip,
            Aggregation.match(criteria),
            Aggregation.group("hasVip.vipLevel").count().as("count")
    );
    AggregationResults<Object> aggregate = mongoTemplate.aggregate(aggregation, Comment.class, Object.class);
    System.out.println(aggregate.getRawResults());
    Document documentResult = aggregate.getRawResults();
    // 取出结果
    List<Map> documents = (List<Map>) documentResult.get("results");
    // 流处理,排序,转型
    List<UserCompanyVipScoreDto> vipScoreDtoList = documents.stream().map(map -> new UserCompanyVipScoreDto(
            Integer.valueOf(((List) map.get("_id")).get(0).toString()),
            Integer.valueOf(map.get("count").toString())
    )).sorted(Comparator.comparing(UserCompanyVipScoreDto::getVipLevel)).collect(Collectors.toList());
    System.out.println(vipScoreDtoList);
}

在这里插入图片描述

关联两张表,分别进行筛选并且按照其中一张表的某字段出现频率排序,并显示详细信息

// 查询所有在投票的idea按照like次数降序排序,要求返回时携带相关idea内容
@Override
    public List<ShareIdeaView> userIdeaFindPage(Integer page, Integer size, Integer appVersion, Integer status) {
        // 先在topicLike中查所有类型为1的,点赞数排行的分页数据(这里只查idea的点赞排行)

        // idea关联like,
        LookupOperation userIdea = LookupOperation.newLookup()
                // 这里是次表的名称[主表是你下面执行查询所写的哪个表]
                .from("ad_user_idea")
                // 这里是主表打算用哪个字段来和上面那个次表进行关联
                .localField("_id")
                // 这里是次表用来和主表进行关联的字段
                .foreignField("_id")
                // 这样他们就有了一个临c时表,给他取个别名,注意这里的名字直接影响了查询结果的封装字段名,稍后用来接结果的那个对象的属性名也要是这个
                .as("userIdea");

        // 点赞表筛选
        Criteria likeCriteria = new Criteria();
        // 这里是在主表执行的筛选条件
        likeCriteria.andOperator(
                // 查询idea的点赞
                Criteria.where("likeType").is(TopicLikeTypeEnum.IDEA_LIKE.getType())
        );

        // idea表筛选
        Criteria ideaCriteria = new Criteria();
        ideaCriteria.andOperator(
                // 这里就用上面的别名idea.status指定关联临时表中的字段晒许安关系
                Criteria.where("userIdea.status").is(status),
                Criteria.where("userIdea.appVersion").is(appNumVersion+1)
        );

        // 拼装查询条件
        Aggregation aggregation = Aggregation.newAggregation(
                // 添加筛选流程
                Aggregation.match(likeCriteria),
                // 添加分组规则,这里使用count统计次数,赋予别名likeCount
                Aggregation.group("topicOid").count().as("likeCount"),
                // 添加排序规则,[注意这里由于处理器使用在分组后,刚好需要按照分组统计后AS的别名进行排序,所以这里的排序字段一定要和AS对应]
                Aggregation.sort(Sort.by(Sort.Order.desc("likeCount"))),
                // 进行分页配置
                userIdea,
                Aggregation.match(ideaCriteria),
                Aggregation.skip(Long.valueOf((page - 1) * size)),
                Aggregation.limit(size)
        );

        long start = System.currentTimeMillis();
        // 执行管道查询,,,注意这里参数中的第二个为collectionName,也就是集合名称,对应mongodb中的表名(管道,集合名称[主表],接收结果的结果集)
        AggregationResults<TopicLikeSortCount> ideaCount = mongoTemplate.aggregate(aggregation, TopicLike.class, TopicLikeSortCount.class);
        log.error("MongoDB查询耗时:{}ms",System.currentTimeMillis()-start);
        // 这里和上一条的泛型字段一定要包含id和我们使用的AS likeCount否则无法封装
        List<TopicLikeSortCount> likeSortCounts = ideaCount.getMappedResults();
        List<ShareIdeaView> ideaViews = likeSortCounts.stream()
                .map(like -> new ShareIdeaView(
                        BeanUtil.copyProperties(like.getUserIdea(), UserIdeaView.class),
                        like.getLikeCount())).collect(Collectors.toList());
        log.error("MongoDB整体查询耗时:{}ms",System.currentTimeMillis()-start);
        return ideaViews;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值