mongoTemplate支持多表联查 排序 条件筛选 分页 去重分组

3 篇文章 0 订阅

在这里插入图片描述

说明

需求:
列表展示需要对mongo的两表进行连表查询,且根据两个不同的表中指定字段去排序分页展示,其中包含对两个表不同条件的筛选。

以下案例:
school主表和class次表,查询school里面为新民小学,并且名字叫高老师的所有班级,返回班级里面的所有学生的姓名、年龄。案例简单看看,主要看代码技术点。

代码

数据总条数

public long getTotal(String teacherName, String startTime, String endTime) {
        LookupOperation lookup = LookupOperation.newLookup()
        		//次表名称
                .from("class")
                //主表关联字段
                .localField("classId")
                //次表关联字段 
                .foreignField("classId")
                //临时表明 主要是给次表用
                .as("er");
                
		//数据类型转换,classId在一个表是string,另一个表是objectId类型,如果没有转换需求可忽略
        AddFieldsOperation addFieldsOperation = AddFieldsOperation
                .addField("classId")
                .withValue(ConvertOperators.ToObjectId.toObjectId("$classId")).build();

		//次表查询条件
        Criteria criteria = Criteria.where("er.teacher").is("高老师");
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            criteria.and("er.createTime").gte(dateToISODate(strToDateLong(startTime))).lte(dateToISODate(strToDateLong(endTime)));
        }

        Aggregation countAgg = Aggregation.newAggregation(
                //主表查询条件
                Aggregation.match(Criteria.where("schoolName").is("新民小学")),
                addFieldsOperation,
                lookup,
                //lookup以下是次表查询条件和分组
                Aggregation.unwind("er"),
                Aggregation.match(criteria),
                Aggregation.group("_id:null").count().as("count")
        );
        //school是主表名称
        AggregationResults<Map> resultCount = mongoTemplate.aggregate(countAgg, "school", Map.class);
        List<Map> countList = resultCount.getMappedResults();
        long count = 0L;
        if (countList.size() > 0) {
        // 拿到总条数,可以用于业务分页计算
            count = Long.parseLong(countList.get(0).get("count").toString());
        }
        return count;
    }

数据总体data

public List<ClassVo> infoData(String teacherName, String startTime, String endTime, Integer pageNum, Integer pageSize) {
        LookupOperation lookup = LookupOperation.newLookup()
        		//次表名称 班级
                .from("class")
                //主表关联字段
                .localField("classId")
                //次表关联字段 
                .foreignField("classId")
                //临时表明 主要是给次表用
                .as("er");

       //数据类型转换,classId在一个表是string,另一个表是objectId类型,如果没有转换需求可忽略
        AddFieldsOperation addFieldsOperation = AddFieldsOperation
                .addField("classId")
                .withValue(ConvertOperators.ToObjectId.toObjectId("$classId")).build();

		//次表查询条件
        Criteria criteria = Criteria.where("er.teacher").is(teacherName);
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            criteria.and("er.createTime").gte(dateToISODate(strToDateLong(startTime))).lte(dateToISODate(strToDateLong(endTime)));
        }

        Aggregation countAgg = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("schoolName").is("新民小学")),
                addFieldsOperation,
                lookup,
                Aggregation.unwind("er"),
                Aggregation.match(criteria),
                //主表字段
                Aggregation.project("classId", "status")
                //次表字段都要用【er.】才能获取到
                        .andInclude("er._id", "er.tearcher", "er.student.name", "er.student.age"),
                //根据主表状态和次表年龄降序排序        
                Aggregation.sort(Sort.Direction.DESC, "status", "age"),
                //去重 连表查询避免不了一对多关系 会查出重复数据可以用group对id进行分组去重 .first可以理解为返回的字段as为返回的别名,这里可以理解为sql返回后的最终字段 如果要返回学生名称 不需要用er.student.name 直接name字段获取
                Aggregation.group("_id").first("_id").as("id")
                        .first("tearcher").as("tearcher")
                        .first("name").as("name")
                        .first("age").as("age"),
                //分页
                Aggregation.skip((pageNum - 1) * pageSize),
                Aggregation.limit(pageSize)
        );
        
        //school是主表名称
        AggregationResults<ServerRecordVo> resultCount = mongoTemplate.aggregate(countAgg, "school", ServerRecordVo.class);
        List<ServerRecordVo> vos = resultCount.getMappedResults();
        return vos;
    }

就先说到这 \color{#008B8B}{ 就先说到这} 就先说到这
在下 A p o l l o \color{#008B8B}{在下Apollo} 在下Apollo
一个爱分享 J a v a 、生活的小人物, \color{#008B8B}{一个爱分享Java、生活的小人物,} 一个爱分享Java、生活的小人物,
咱们来日方长,有缘江湖再见,告辞! \color{#008B8B}{咱们来日方长,有缘江湖再见,告辞!} 咱们来日方长,有缘江湖再见,告辞!

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Data MongoDB中,可以使用MongoTemplate进行联表查询。具体来说,可以使用MongoTemplate的aggregate方法来执行聚合查询,通过聚合管道操作符实现联表查询。 以下是一个使用MongoTemplate进行联表查询的示例: ```java import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.LookupOperation; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.stereotype.Repository; import java.util.List; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.core.query.Criteria.*; @Repository public class ExampleRepository { private final MongoTemplate mongoTemplate; public ExampleRepository(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } public List<Example> findByCategoryId(String categoryId) { LookupOperation lookupOperation = LookupOperation.newLookup() .from("category") .localField("categoryId") .foreignField("_id") .as("category"); TypedAggregation<Example> aggregation = newAggregation(Example.class, match(where("categoryId").is(categoryId)), lookupOperation, unwind("category"), project("title", "category.name").andExclude("_id")); return mongoTemplate.aggregate(aggregation, Example.class).getMappedResults(); } } ``` 在此示例中,我们使用LookupOperation来连接`Example`和`Category`集合,通过匹配`categoryId`和`_id`字段来联表查询。然后,我们使用unwind操作符展开`category`字段中的数组,以便进行后续的投影操作。最后,我们使用project操作符来选择需要返回的字段并排除`_id`字段。 请注意,在此示例中,我们假设存在一个名为`category`的集合,其包含`_id`和`name`字段。如果你的数据模型与此不同,请相应地更改代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值