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 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 map,String tag,String city)
throws Exception {
kspositionrange=kspositionrange*kaoshengksposition/100;
map.put("result", true);
List operations=new ArrayList();
//添加年份条件
operations.add(Aggregation.match(Criteria.where("year").is(year)));
//关联school表获取city和tag
operations.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
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 addPageInfoAndGetResult(List 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 aggRes = mongoTemplate.aggregate(aggregation,
"ptyxzslqtjb", Map.class);
List raws=aggRes.getMappedResults();
return raws;
}
/**
* 获取总数
* @param countOperations
* @return
*/
public int getTotalCount(List countOperations){
int count=0;
countOperations.add(Aggregation.group().count().as("count"));
Aggregation countaggregation = Aggregation.newAggregation(countOperations);
AggregationResults countRes = mongoTemplate.aggregate(countaggregation, "ptyxzslqtjb", Map.class);
List coutMapRes = countRes.getMappedResults();
if(coutMapRes!=null&&coutMapRes.size()>0){
count = (Integer)coutMapRes.get(0).get("count");
}
return count;
}
4.数组查询方法
$all、$size、$slice、$elemMatch
语法:
{ field:{ $all: [
例子:
db.orders.find({"books":{$all:["java","mongo"]}})
查找books包含java、mongo的文档数据
语法:
{field: {$size: number } }
例子:
>db.orders.find({"books":{$size:2}})
语法:
>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个元素
我们先保存数据
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
}
]
}
])
语法:
>{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的文档,无关的文档没有返回,方便我们处理数据,这样也可以节省传输数据量,减少了内存消耗,提高了性能,在数据大时,性能很明显的。