Java使用mongodb进行数据存储及多表关联,多条件查询

前言: 

    在开发的过程中,由于持久层使用的是非关系型数据库mongodb,涉及到列表查询的多表关联查询,在实现此功能的过程中出现了不少问题,做下记录方便以后遇到此类问题可以快速的解决,同时为遇到此类问题的小伙伴提供一点帮助。

    注: Java操作mongodb数据库存储数据,数据访问层需继承 MongoRepository 接口,本实例为Spring boot项目

import org.springframework.data.mongodb.repository.MongoRepository;

public interface TenantRepository extends MongoRepository {

}

条件查询

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @ApiOperation("租户列表")
    public ObjectRestResponse> list() {
        Tenant tenant=new Tenant();
        tenant.setDisabled(false);
        Example example = Example.of(tenant);
        List list = tenantRepository.findAll(example);
        return new ObjectRestResponse>().data(list);
    }

多条件分页查询

    @RequestMapping(value = "/pageList", method = RequestMethod.GET)
    @ApiOperation("租户分页查询")
    public TableResultResponse pageList(Tenant query) {
        Pageable pageable = PageRequest.of(query.getPage()-1, query.getLimit(), Sort.by(Sort.Direction.DESC,"createTime"));
        //创建匹配器,即如何使用查询条件
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询
                .withIgnoreCase(true) //改变默认大小写忽略方式:忽略大小写
                .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains()) //采用“包含匹配”的方式查询
                //.withMatcher("processStatus", ExampleMatcher.GenericPropertyMatchers.regex())
                .withIgnorePaths("page", "limit");  //忽略分页属性,不参与条件查询
        Example example = Example.of(query,matcher);
        Query qy = new Query(Criteria.byExample(example));
        //时间段查询条件
        if (query.getStartTime() != null&& query.getEndTime()!= null){
            qy.addCriteria(Criteria.where("createTime").gte(query.getStartTime()).lte(query.getEndTime()));
        }
        //计算总数
        long total = mongoTemplate.count(qy, Tenant.class);
        //查询结果集
        List list = mongoTemplate.find(qy.with(pageable), Tenant.class);
        return new TableResultResponse(total, list);
    }

 

关联查询语句:

    假设先 A 表查出符合条件的数据,根据 A 表符合条件数据查询B表符合条件的数据

mongo查询语句:

db.getCollection('A').aggregate([
        {
        $lookup:{
                    from:'B',
                    localField:'userid',
                    foreignField:'userid',
                    as:'userinfo'
                }
        }, 
        {
         $unwind:'$userrole'//把一个数组展成多个,就比如说按多表连查的userrole数组中有10数据,那么用$unwind将把一条带数组的数据分成10条,这10条数据除了userrole不同之外,其它数据都是相同的,就类似于一个展开操作
        },
        {
         $match:{'username':'zhangsan'}
        },
        {
          $group:{
                    _id:{
                            userid:'$userid',//这个属性必须是要A表中有的
                            userrole:'$userrole.roleid',//A表中有一个集合,里面存放的对象有一个名为roleid的属性
                        },
                    operateTime:{
                            $last:'$operateTime'//取A表操作时间最后一条件数
                        }
                    info:{
                            $first:'$userinfo'//因为数组的扩展,造成了大量的重复数据(只有userrole不同),$first是只取最新的一条
                        }
                }
        },
        {
            $sort:{'operateTime':-1}//操作时间倒序,-1:倒序,1:升序
        },
        {
            $skip:0//跳过几条数据,也就是从第几条数据开始取
        },
        {
            $limit:5//每页显示几条数据
        }
]);

java整合查询语句代码

        //定义分组字段
        String[] groupIds = new String[] {"$userid","$userrole.roleid"};
        //定义查询条件
        Criteria criteria = new Criteria();
        //相当于where username = "zhangsan"
        criteria.and("username").is("zhangsan");
        //相当于 where age not in("15","20")
        criteria.and("age").nin("15","20");
        //in操作对应的语句
        //criteria.and("").in();
        //定义排序条件
        Sort sort = new Sort(Direction.DESC,"operateTime");
        //联合查询总条数,分页用
        Aggregation aggregationCount = Aggregation.newAggregation(Aggregation.match(criteria);//查询条件
        Aggregation.group(groupIds);//分组字段
        //联合查询条件
        Aggregation newAggregation = Aggregation.newAggregation(
                Aggregation.lookup('B','userid','userid','userinfo'),//从表名,主表联接字段,从表联接字段,别名
                Aggregation.unwind("$userrole"),
                Aggregation.match(criteria),
                Aggregation.group(groupIds)
                        .last("$operateTime").as("operateTime")//取值,起别名
                        .first("$userinfo").as("info"),
                Aggregation.sort(sort),
                Aggregation.skip(pageSize*(pageNumber-1L)),//Long类型的参数
                Aggregation.limit(pageSize)
        );
        //查询
        AggregationResults aggregate = mongoTemplate.aggregate(
                newAggregation ,"A",BasicDBObject.class//A表,是查询的主表
        );
        int count = mongoTemplate.aggregate(aggregationCount ,"A",BasicDBObject.class).getMappedResults().size();
        //组装分页对象
        Page pager = new Page<>(aggregate.getMappedResults(),count,pageSize,pageNumber,page*(pageNumber-1));
        //对象转换
        将BasicDBObject转换成前面需要的类型.....
 
 

其它mongodb数据库操作

    @Resource
    private TenantRepository tenantRepository;
    @Resource
    private MongoTemplate mongoTemplate;

    @RequestMapping(method = RequestMethod.POST)
    @ApiOperation("新增或修改租户,ID不为空执行修改操作")
    public ObjectRestResponse add(@RequestBody Tenant tenant) {
        tenant.setDisabled(false);
        tenant.setCreateTime(new Date());
        tenantRepository.save(tenant);
        return new ObjectRestResponse();
    }

    @RequestMapping(value = "", method = RequestMethod.PUT)
    @ApiOperation("禁用租户")
    public ObjectRestResponse updateIndicator(@RequestBody Tenant tenant) {
        tenant.setDisabled(true);
        tenant.setCancelTime(new Date());
        tenantRepository.save(tenant);
        return new ObjectRestResponse();
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    @ApiOperation("租户详情")
    public ObjectRestResponse get(@PathVariable String id) {
        Tenant tenant = tenantRepository.findById(id).get();
        return new ObjectRestResponse().data(tenant);
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    @ApiOperation("删除租户")
    public ObjectRestResponse delete(@PathVariable String id) {
        tenantRepository.deleteById(id);
        return new ObjectRestResponse<>();
    }

等等其它方法操作请自行通过 " ."' 方式调用

Java使用mongodb进行数据存储及多表关联,多条件查询_第1张图片

你可能感兴趣的:(#,MongoDB,#,spring,boot,#,Spring,cloud)