mongodb关联表查询
1.首先自定义一个查询的Operation
package com.pica.wx.bean;import com.mongodb.DBObject;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;/*** @author lqx* @create 2018-09-01 10:41*/public class CustomAggregationOperation implements AggregationOperation {private DBObject operation;public CustomAggregationOperation (DBObject operation) {this.operation = operation;}public DBObject toDBObject(AggregationOperationContext context) {return context.getMappedObject(operation);}}
关联表查询如下
/*** 获取表单数据* @param isZYD 是不是志愿单页面0不是1是* @param ksmc* @param year* @param kaoshengksposition* @param kspositionrange* @param baowenchong* @param cbatch* @param yxdm* @param yxmc* @param currentPage* @param pageSize* @param sort_column* @param sort_direction* @param map* @param tag* @param city* @return* @throws Exception*/public Map<String,Object> findSchoolBWC(Integer isZYD,String ksmc, int year, int kaoshengksposition, int kspositionrange, String baowenchong, String cbatch,String yxdm, String yxmc, int currentPage, int pageSize, String sort_column, String sort_direction, Map<String, Object> map,String tag,String city)throws Exception {kspositionrange=kspositionrange*kaoshengksposition/100;map.put("result", true);List<AggregationOperation> operations=new ArrayList<AggregationOperation>();//添加年份条件operations.add(Aggregation.match(Criteria.where("year").is(year)));//关联school表获取city和tagoperations.add(new CustomAggregationOperation(new BasicDBObject("$lookup",new BasicDBObject("from", "schools").append("localField","yxmc").append("foreignField", "name").append("as", "schools"))));//添加批次条件operations.add(Aggregation.match(Criteria.where("cbatch").is(cbatch)));//添加科目条件operations.add(Aggregation.match(Criteria.where("ksmc").is(ksmc)));//添加排序operations.add(Aggregation.sort(new Sort(new Sort.Order(sort_direction.toLowerCase().equals("desc") ? Direction.DESC:Direction.ASC,sort_column))));//添加城市条件if(StringUtils.isNotBlank(city)){operations.add(Aggregation.match(Criteria.where("schools.cityname").is(city)));}//添加tag条件if(StringUtils.isNotBlank(tag)){operations.add(Aggregation.match(Criteria.where("schools.tags").regex(tag)));}int count=0;//总数List<Map> raws=new ArrayList<Map>();int baoTotalPage=0;//bao总页数int wenTotalPage=0;//wen总页数int chongTotalPage=0;//chong总页数//控制显示字段if (baowenchong.toLowerCase().equals("bao")||isZYD==1) {//创建bao查询集合List<AggregationOperation> baoOperations=new ArrayList<AggregationOperation>();baoOperations.addAll(operations);baoOperations.add(Aggregation.match(Criteria.where("fmaxksposition").gte(kaoshengksposition +kspositionrange)));//获取总数List<AggregationOperation> countOperations=new ArrayList<AggregationOperation>();countOperations.addAll(baoOperations);int baoCount=getTotalCount(countOperations);count+=baoCount;baoTotalPage=(baoCount + pageSize -1) / pageSize;//添加分页并获取结果集//获取要显示的字段baoOperations.add(getBaseShowFiled("bao"));List<Map> baoRaws=addPageInfoAndGetResult(baoOperations,currentPage,pageSize);raws.addAll(baoRaws);}if(baowenchong.toLowerCase().equals("wen")||isZYD==1){//创建wen查询集合List<AggregationOperation> wenOperations=new ArrayList<AggregationOperation>();wenOperations.addAll(operations);wenOperations.add(Aggregation.match(Criteria.where("fmaxksposition").lte(kaoshengksposition-kspositionrange)));wenOperations.add(Aggregation.match(Criteria.where("fminksposition").gte(kaoshengksposition+kspositionrange)));//获取总数List<AggregationOperation> countOperations=new ArrayList<AggregationOperation>();countOperations.addAll(wenOperations);int wenCount=getTotalCount(countOperations);count+=wenCount;wenTotalPage=(wenCount + pageSize -1) / pageSize;//添加分页并获取结果集//获取要显示的字段CustomAggregationOperation projectOperation=getBaseShowFiled("wen");wenOperations.add(projectOperation);List<Map> wenRaws=addPageInfoAndGetResult(wenOperations,currentPage,pageSize);raws.addAll(wenRaws);}if(baowenchong.toLowerCase().equals("chong")||isZYD==1){//创建chong查询集合List<AggregationOperation> chongOperations=new ArrayList<AggregationOperation>();chongOperations.addAll(operations);chongOperations.add(Aggregation.match(Criteria.where("fminksposition").lte(kaoshengksposition-kspositionrange)));//获取总数List<AggregationOperation> countOperations=new ArrayList<AggregationOperation>();countOperations.addAll(chongOperations);int chongCount=getTotalCount(countOperations);count+=chongCount;chongTotalPage=(chongCount + pageSize -1) / pageSize;//添加分页并获取结果集//获取要显示的字段chongOperations.add(getBaseShowFiled("chong"));List<Map> chongRaws=addPageInfoAndGetResult(chongOperations,currentPage,pageSize);raws.addAll(chongRaws);}Page page=new Page();page.setCurrentPage(currentPage);page.setPageSize(pageSize);//初始化数组List<Integer> totalPages = new ArrayList<Integer>();totalPages.add(baoTotalPage);totalPages.add(wenTotalPage);totalPages.add(chongTotalPage);//获取最大页数作为总页数page.setTotalPage(Collections.max(totalPages));page.setRows(raws);page.setTotalCount(count);map.put("data", page);//获取往年情况if(page.getRows()!=null&&page.getRows().size()>0){chanWangNianLQQK(map,page,ksmc,year,cbatch,kaoshengksposition);}return map;}
3.如果要添加自定义字段,上面方法中用到的方法如下
/*** 获取要显示的字段* @param baowenchong* @return*/public CustomAggregationOperation getBaseShowFiled(String baowenchong){CustomAggregationOperation projectOperation=new CustomAggregationOperation(new BasicDBObject("$project",new BasicDBObject("year", 1).append("yxmc",1).append("ksmcname", 1).append("cbatch", 1).append("cbatchname", 1).append("yxdm", 1).append("yxmc", 1).append("plan", 1).append("planenrollment", 1).append("enrollment", 1).append("fmax", 1).append("fmin", 1).append("favg", 1).append("fmaxksposition", 1).append("fminksposition", 1).append("yxsf", 1).append("yxtag", 1).append("schools", 1).append("baowenchong", baowenchong)));return projectOperation;}/*** 添加分页并获取结果集* @param operations* @param currentPage* @param pageSize* @return*/public List<Map> addPageInfoAndGetResult(List<AggregationOperation> operations,Integer currentPage,Integer pageSize){operations.add(Aggregation.skip((long)((currentPage-1)*pageSize)));operations.add(Aggregation.limit((long)pageSize));Aggregation aggregation = Aggregation.newAggregation(operations);AggregationResults<Map> aggRes = mongoTemplate.aggregate(aggregation,"ptyxzslqtjb", Map.class);List<Map> raws=aggRes.getMappedResults();return raws;}/*** 获取总数* @param countOperations* @return*/public int getTotalCount(List<AggregationOperation> countOperations){int count=0;countOperations.add(Aggregation.group().count().as("count"));Aggregation countaggregation = Aggregation.newAggregation(countOperations);AggregationResults<Map> countRes = mongoTemplate.aggregate(countaggregation, "ptyxzslqtjb", Map.class);List<Map> coutMapRes = countRes.getMappedResults();if(coutMapRes!=null&&coutMapRes.size()>0){count = (Integer)coutMapRes.get(0).get("count");}return count;}
4.数组查询方法
对数组根据条件查询
$all、$size、$slice、$elemMatch
(1)$all查找数组中包含指定的值的文档
语法:
{ field:{ $all: [ <value> , <value1> ... ]}
例子:
db.orders.find({"books":{$all:["java","mongo"]}})
查找books包含java、mongo的文档数据
(2)$size 查找数组大小等于指定值的文档
语法:
{field: {$size: number } }
例子:
>db.orders.find({"books":{$size:2}})
(3)$slice查询数组中指定返回元素的个数
语法:
>db.collect.find({},{field:{$slice: number }})
number 说明:
为正数表示返回前面指定的值的个数:例如1 返回数组第一个
为负数表示返回倒数指定的值的个数:例如-1返回数组倒数第一个
例子:
>db.orders.find({"onumber":{$in:["008","009"]}},{books:{$slice:1}})
1)$slice可以查询数组中第几个到第几个
语法:
>db.collect.find({},{field:{$slice:[ number1, number2] }})
跳过数组的number1个位置然后返回number2个数
number1说明:
为正数表示跳到指定值的数组个数:例如2 跳到数组第3个
为负数表示跳到指定值的数组倒数个数:例如-2跳到到数组倒数第3个
例子:
>db.orders.find({"onumber":{$in:["008","009"]}},{books:{$slice:[1,1]}})
跳过books数组第一个元素,现在到数组第二个元素,并返回1个元素
三、对数组内嵌文档查询
我们先保存数据
<span style="font-size:18px;">
db. orders.insert([
{
"onumber" : "001",
"date" : "2015-07-02",
"cname" : "zcy1",
"items" :[ {
"ino" : "001",
"quantity" :2,
"price" : 4.0
},{
"ino" : "002",
"quantity" : 4,
"price" : 6.0
}
]
},{
"onumber" : "002",
"date" : "2015-07-02",
"cname" : "zcy2",
"items" :[ {
"ino" : "001",
"quantity" :2,
"price" : 4.0
},{
"ino" : "002",
"quantity" :6,
"price" : 6.0
}
]
}
])</span>
(1)$elemMatch 文档包含有一个元素是数组,那么$elemMatch可以匹配内数组内的元素并返回文档数据
语法:
>{field:{$elemMatch:{ field1:value1, field2:value2,………}}}
例子:
>db.orders.find({"items":{$elemMatch:{"quantity":2}}})
返回quantity为2的文档
也可以这样查询db.orders.find({"items.quantity":2})
(2) $elemMatch可以带多个查询条件
例子:
>db.orders.find({"items":{$elemMatch:{"quantity":4,"ino":"002"}}})
我们查询数组中的quantity等于4并且ino等于002,但是我们就想返回数组中的quantity等于4并且ino等于002的这个文档,并不想把ino等于001等这些无关的文档返回。
(3)$elemMatch 同样可以用在find方法的第二个参数来限制返回数组内的元素,只返回我们需要的文档
例子:
db.orders.find({"onumber":"001"},{"items":{$elemMatch:{"quantity":4,"ino":"002"}},"cname":1,"date":1,"onumber":1})
我们只返回quantity等于4并且ino等于002的文档,无关的文档没有返回,方便我们处理数据,这样也可以节省传输数据量,减少了内存消耗,提高了性能,在数据大时,性能很明显的。
mongodb关联表查询相关推荐
- MongoDB联表查询aggregate : $lookup
参考:MongoDB联表查询 建表插入数据: db.createCollection("user") db.user.insertMany([{_id: ObjectId(&quo ...
- Mybatis源码分析--关联表查询及延迟加载原理(二)
在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...
- Mybatis实现关联表查询
Mybatis实现关联表查询 6.1. 一对一关联 1). 提出需求 根据班级 id 查询班级信息(带老师的信息) 2). 创建表和数据 [](javascript:void(0)
- MySQL 实现多张无关联表查询数据并分页
MySQL 实现多张无关联表查询数据并分页 1.功能需求 在三张没有主外键关联的表中取出自己想要的数据,并且分页. 2.数据库表结构 水果表: 坚果表: 饮料表: 主要用UNION AL UNION ...
- hibernate mysql 关联查询_hibernate 查询缓存,以及在关联表查询缓存下使用HQL,而不是sql去查询...
什么是查询缓存? 也就是如果开启了查询缓存, 在 没有使用二级缓存的情况下,会 缓存第一次查询出来的数据的id. 第二次查询的时候, 如果查询的参数和查询语句没有变化,那么就会使用 第一次查询的出来的 ...
- MyBatis学习总结(五)——实现关联表查询
2019独角兽企业重金招聘Python工程师标准>>> 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里 ...
- MyBatis学习总结(5)——实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- Mybatis系列(三):Mybatis实现关联表查询
原文链接:http://www.cnblogs.com/xdp-gacl/p/4264440.html 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 ...
- $lookup做关联表查询
两张表格answer和question. #------------------------------------------------------------------------------ ...
最新文章
- 强化学习Reinforcement Learning
- NVIDIA之AI Course:Getting Started with AI on Jetson Nano—Class notes(一)
- what is ssao
- WebSocket使用,包括服务端和客户端(JAVA实现)
- java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)
- linux系统之上搭建maven 之nexus服务篇
- 遇到没有exe文件的驱动
- c++ 二次开发 良田高拍仪_捷易拍sdk开发指南(高拍仪、文件拍摄仪二次开发软件)...
- 老年人计算机培训方案,老年人学电脑从新手到高手
- java openoffic linux_Linux操作系统下安装Openoffice3.2
- gta5 android ps4,gta5导演模式怎么玩好玩_gta5怎么进入导演模式怎么玩ps4导演模式怎么打开_攻略...
- 【PyTorch深度学习项目实战100例】—— 基于CNN实现书法字体风格识别任务 | 第62例
- 什么是 5G CPE
- python 读取doc 和 docx
- pytorch系统学习
- 中科大计算机科学夏令营,2019中科大计算机夏令营机试
- 网络传输中的数据长度
- 删除临时文件夹中的特定名称模式目录
- 社区无人便利店APP开发解决方案
- 【Android控件属性记录】