java操作mongodb之多表联查($lookup)

最近在开发的过程中,一个列表的查询,涉及到了多表的关联查询,由于持久层使用的是mongodb,对这个非关系型数据使用的不是很多,所以在实现此功能的过程中出现了不少问题,现在此做记录,一为加深自己的理解,以后遇到此类问题可以快速的解决,二为遇到同样问题的小伙伴提供一点小小的帮助。

全文分为两部分:

  1. 使用robo3t编写多表关系的查询语句
  2. 将编写的查询语句整合到java项目

多表联查的查询语句:

此处使用的为mongodb的robo3t可视化工具,先说下需求:从A(假如说是日志表)表中查询出符合条件的数据,根据A表中符合条件数据查询B(假如说是信息表)表中的数据,此处也可以将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<BasicDBObject> aggregate = mongoTemplate.aggregate(
    newAggregation ,"A",BasicDBObject.class//A表,是查询的主表
);
int count = mongoTemplate.aggregate(aggregationCount ,"A",BasicDBObject.class).getMappedResults().size();
//组装分页对象
Page<BasicDBObject> pager = new Page<>(aggregate.getMappedResults(),count,pageSize,pageNumber,page*(pageNumber-1));
//对象转换
将BasicDBObject转换成前面需要的类型.....


行文时间短促,疏漏之处在所难免,欢迎大家批评指定。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
MongoDB中,$lookup操作符可以用于实现多表连接查询。它可以将两个集合中的文档进行关联,并返回一个新的文档,其中包含了两个集合中匹配的文档信息。而在进行$lookup操作之后,我们可以使用$project操作符来对查询结果进行进一步的处理,以选择需要显示的字段或者添加新的字段。 例如,假设我们有两个集合"orders"和"customers",它们的结构分别如下: orders集合: ``` { "_id": ObjectId("5f94e5c0d286db2d3ad3a71c"), "order_id": 1, "customer_id": ObjectId("5f94e5c0d286db2d3ad3a71a"), "product": "computer", "amount": 3 } ``` customers集合: ``` { "_id": ObjectId("5f94e5c0d286db2d3ad3a71a"), "name": "Tom", "age": 25, "address": "New York" } ``` 现在我们希望查询orders集合中的文档,并将其与customers集合中的文档进行关联,以获取订单对应的客户信息。我们可以使用以下的$lookup和$project操作来实现: ``` db.orders.aggregate([ { $lookup: { from: "customers", localField: "customer_id", foreignField: "_id", as: "customer_info" } }, { $project: { "order_id": 1, "product": 1, "amount": 1, "customer_name": "$customer_info.name", "customer_age": "$customer_info.age", "customer_address": "$customer_info.address" } } ]) ``` 在上述代码中,$lookup操作符用于将orders集合中的"customer_id"字段与customers集合中的"_id"字段进行关联,并将匹配的文档信息存储在一个新的字段"customer_info"中。而$project操作符则用于对查询结果进行处理,选择需要显示的字段,并添加新的字段"customer_name"、"customer_age"和"customer_address"来显示客户的姓名、年龄和地址。 参考资料: - MongoDB官方文档:$lookup - MongoDB官方文档:$project

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值