MongoTemplate联表查询

关于mongoTemplate的联表查询,之前的内容没有描述清楚,这次清空了重写。

案例关系:org通过 orgId一对多 关联task,需要查出每个org和其最新的一个task

org ——orgId——> task1、task2、…

代码:

            LookupOperation lookup = LookupOperation.newLookup()
                    .from("task") //次表
                    .localField("orgId") //主表关联字段
                    .foreignField("orgId") //次表关联字段
                    .as("link"); //临时集合别名

            Aggregation aggregation = Aggregation.newAggregation(
                    //主表条件
                    Aggregation.match(Criteria.where("isDel").ne(1)),
                    //联表
                    lookup,
                    //次表条件 
                    Aggregation.unwind("link"),
                	Aggregation.match(Criteria.where("link.isDel").ne(1)),
                    Aggregation.sort(Sort.by(Sort.Order.desc("link.createTime"))),
                    Aggregation.group("task.orgId")
                           	.first("link.title").as("title")
                            .first("orgId").as("orgId")
                            .first("orgName").as("orgName")
                            .first("link.createTime").as("createTime"), 
                    Aggregation.sort(Sort.by(Sort.Order.desc("createTime"),Sort.Order.desc("orgId"))),
                    Aggregation.project("orgId","title","createTime")
            );

            List<Org> orgs = mongoTemplate.aggregation(aggregation,Org.class).getMappedResults();

接下来根据代码分析:

  1. 首先是主表条件,就是对最后mongoTemplate.aggregation(aggregation,Org.class).getMappedResults()Org.Class对应的表直接进行操作,这一步的结果大致如下:

    [
        {
            "orgId":"",
            "orgName":"",
            "createTime":""
        },
        ....
    ]
    
  2. Lookup进行联表操作

                LookupOperation lookup = LookupOperation.newLookup()
                        .from("task") //次表
                        .localField("orgId") //主表关联字段
                        .foreignField("orgId") //次表关联字段
                        .as("link"); //临时集合别名
    

    这一步是把次表中满足关联条件(关联字段相等,类似于sql的inner join)的数据查出来作为一个数组,用as指定的别名嵌入到上一步的操作中,此时的结果大致如下:

    [
        {
            "orgId":"",
            "orgName":"",
            "createTime":"",
            "link":[
                {
                    "taskId":"",
                    "orgId":"",
                    "title":"",
                    "createTime":""
                },
                ...
            ]
        },
        ....
    ]
    
  3. 次表条件,是将步奏2的结果进行操作。由于联表的结果是个内嵌的数组,如果需要的是一对一的关系,需要进行Aggregation.unwind()再进行操作。例如此处要取出每个org最新的一个task:

    					//次表条件,对步奏2的结果集进行操作
                        Aggregation.unwind("link"), //拆分link
                    	Aggregation.match(Criteria.where("link.isDel").ne(1)), //过滤条件
                        Aggregation.sort(Sort.by(Sort.Order.desc("link.createTime"))), //创建时间倒序,在下一步分组中取出排序后的首位 
    

    此时的结果集:

    [
        {
            "orgId":"o1",
            "orgName":"",
            "createTime":"",
            "link":{
                "taskId":"t1",
                "orgId":"o1",
                "title":"tt1",
                "createTime":"time4"
            }
        },
        {
            "orgId":"o1",
            "orgName":"",
            "createTime":"",
            "link":{
                "taskId":"t2",
                "orgId":"o1",
                "title":"tt2",
                "createTime":"time3"
            }
        },
        {
            "orgId":"o2",
            "orgName":"",
            "createTime":"",
            "link":{
                "taskId":"t3",
                "orgId":"o2",
                "title":"tt3",
                "createTime":"time2"
            }
        },
        {
            "orgId":"o2",
            "orgName":"",
            "createTime":"",
            "link":{
                "taskId":"t4",
                "orgId":"o2",
                "title":"tt4",
                "createTime":"time1"
            }
        },
        ....
    ]
    //其中,time1<time2<time3<time4
    

    再在此基础上进行分组:

                        ...
                        //分组操作,取首位数据,并指定需要字段的别名(分组字段的值会默认放在"_id"上)
    					Aggregation.group("task.orgId") 
                            	.first("link.title").as("title")
                                .first("orgId").as("orgId")
                                .first("orgName").as("orgName")
                                .first("link.createTime").as("createTime"), 
                        Aggregation.project("orgId","title","createTime")
    

    最后的结果集大致如下:

    [
        {
            "orgId":"o1",
            "title":"tt1",
            "createTime":"time4"
        },
        {
            "orgId":"o2",
            "title":"tt2",
            "createTime":"time2"
        },
    ]
    

总结

  1. 在LookupOperation前的操作,针对主表操作
  2. LookupOperation,指定关联doc,关联字段,和联表结果集别名。并将结果集以数组形式嵌入到**<1>**的对应结果中。
    此时整个结果集只会剩下存在关联关系的数据(inner join
  3. 在LookupOperation后的操作,针对<2>的结果集进行操作
  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
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`字段。如果你的数据模型与此不同,请相应地更改代码。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值