目录
基本用法
/**
* 分页查询所有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;
}