这个aggregate在mongodb中算是一个非常重量级的工具了,而且pipeline的管道模型的理论就是后面操作的数据源来源于上一次操作的结果
数据库中Aggregation 操作:
eg.
db.getCollection('follow_schedule').aggregate( [
{ "$match" : { "attention_timestamp" : { "$gte" : 1517414400000 , "$lte" : 1519833599000}}} ,
{ "$match" : { "doctorid" : "dt221955" , "way" : "来院随访"}} ,
{ "$group" : { "_id" : "$attention_timedot" , "count" : { "$sum" : 1} } }
])
常用操作说明:
数据库操作 |
说明 |
Spring data |
$match
|
用于筛选数据,{}中可以放入多条条件,多个条件用” , ”隔开 |
Aggregation.match(New Criteria()), |
$group |
分组,语义同SQL中的“group by”;”_id”为分组字段,是必须的,”count” 为对每个组执行的表达式计算(count为自定义名字)。表达式计算如下。 |
Aggregation.group("attention_timedot").count().as("count") |
$project |
指定哪些字段将会包含在输出中。默认情况下“_id”字段一定被包含,除非显式指定“_id : 0”才能排除掉;“0”或者false表示“不包含”,“1”或者true表示包含 |
Aggregation.project("doctorid","attention_timedot","count") |
$unwind |
将指定的数组结构拆解成多条document,其中指定的Field必须是数组 |
Aggregation.unwind("数组列名"), |
$limit $skip $sort |
同Query中的limit、skip、$sort限定符 |
Aggregation.sort(newSort(new Order(Direction.DESC, "count"))), Aggregation.skip(0), Aggregation.limit(10), |
|
|
Aggregation.project("d").and("").previousOperation().and("").nested(Aggregation.bind("", "")); |
Group可进行的表达式计算
$sum:对每个组指定字段值进行累加计算。忽略非数字的值。
$avg: 对每个group进行“平均值”,忽略非数字的值。
$first: 返回每个group的第一条数据,顺序有$sort决定,如果没有排序,默认为文档的自然存储顺序
$last: 返回每个group的最后一条数据,顺序有$sort决定,如果没有排序,默认为文档的自然存储顺序
$max、$min:获取每个group中最大、最小值
Spring data中:
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(
New Criteria(TableFieldName.attention_timestamp)
.gte(attrmap.get(TableFieldName.start_time))
.lte(attrmap.get(TableFieldName.end_time))
), // 条件
Aggregation.group("attention_timedot").count().as("count")//分组字段
Aggregation.project("doctorid","attention_timedot","count")//返回字段
Aggregation.sort(new Sort(new Order(Direction.DESC, "count"))), // 排序
Aggregation.skip(0), // 过滤
Aggregation.limit(10) ,// 页数
Aggregation.lookup("doctor","doctorid","userid","inventory_docs")//多表联合查询
);
AggregationResults<BasicDBObject> results = mongoTemplate.aggregate(agg, "follow_schedule",BasicDBObject.class);
List<BasicDBObject> cat1UpdateCountList = results.getMappedResults();
其中:mongoTemplate.aggregate(agg, "follow_schedule",BasicDBObject.class);
第一个参数为Aggregation 第二个参数为要查询的表名 第三个参数为返回的数据类型
$lookup做多表关联处理
db.getCollection('edhealth').aggregate(
[
{
$lookup:
{
from: "edhealth_record", //要关联的表
localField: "userid",//当前表需要关联的键
foreignField: "elderId",//外键,关联表对应的键
as: "inventory_docs"//对应的外键集合的数据
}
},
{ $project : { "userid":1,"waist":1,"bloodType":1,"height":1, "inventory_docs":1}} //要显示的字段
]
)
数据库中去重操作:
eg.查询给dt439815打过电话的人
db.getCollection('vcall_record').distinct("called",{"caller":"dt439815"})
第一个参数为目标去重字段,第二个参数为筛选条件,筛选条件写入{}中,多个用“,”隔开
Spring data 中
Query query = Query.query(Criteria.where("caller").is("dt439815"));
mongoTemplate.getCollection("vcall_record").distinct("called", query.getQueryObject());
示例1:
db.getCollection('jg_geracomium').aggregate([{$match:{"_id":"gd02137175"}},
{$lookup:{from:"jg_room",localField:"_id",foreignField:"geracomiumId",as:"result"}},
{$project:{"_id":0,"result":1}},{$unwind:"$result"},
{$lookup:{from:"jg_resthomebed",localField:"result._id",foreignField:"roomId",as:"data"}},
{$unwind:"$data"},
{$group:{"_id":"$data.roomId","count":{$min:"$data.price"}}}
])
示例2:
db.getCollection('user').aggregate([{$lookup:
{from:"user_account",localField:"userId",foreignField:"userId",as:"data"}},{$project:{"userId":1,"nickname":1,"data.accountId":1,"data.accountType":1,"data.accountMoney":1}},{$unwind:"$data"},{$match:{"data.accountId":"ac123456"}}])
示例3:
db.getCollection('jg_childUser').aggregate([ {$match:{"telephone":"18667945326"}},
{$lookup:
{from:"jg_orderInfo",localField:"telephone",foreignField:"userTelephone",as:"data"}},
{$project:{"nickName":1,"telephone":1,"data.orderNum":1,"data.userTelephone":1}},
{$unwind:"$data"},
{$group:{"_id":"$telephone","count":{$sum:1}}}
])
示例4:
db.getCollection('jg_childUser').aggregate([
{"$group":{"_id":"$telephone"}},
{ "$lookup" :
{ "from" : "jg_orderInfo" , "localField" : "_id" , "foreignField" : "userTelephone" , "as" : "data"}} ,
{"$group":{"_id":"$_id","count":{"$sum":1}}},
{ "$lookup" :
{ "from" : "jg_childUser" , "localField" : "_id" , "foreignField" : "telephone" , "as" : "dd"}} ,
{"$group":{"_id":{"telephone":"$_id","count":"$count"},"first":{"$first":"$dd"}}},
{"$sort":{"first.createTimestamp":-1}},
{"$limit":10},
{"$skip":0}
])
对应spring-date
Aggregation newAggregation = Aggregation.newAggregation(Aggregation.group("telephone"),
Aggregation.lookup("jg_orderInfo", "_id", "userTelephone", "data"),
Aggregation.unwind("data"),
Aggregation.group("_id").count().as("count"),
Aggregation.lookup("jg_childUser", "_id", "telephone", "reslut"),
Aggregation.unwind("reslut"),
Aggregation.group("_id","count").first("reslut").as("first"),
Aggregation.sort(new Sort(new Order(Direction.DESC, "first.createTimestamp")))
);
示例5
db.getCollection('jg_childUser').aggregate([
{"$match":{"telephone":{$ne:null}}},
{"$group":{"_id":"$telephone"}},
{"$lookup":
{"from" : "jg_orderInfo","localField":"_id","foreignField":"userTelephone","as":"data"}},
{"$unwind":"$data"},
{"$group":{"_id":"$_id","count":{"$sum":1}}},
{"$match":{"count":{$gt:1}}},
{"$lookup":
{"from":"jg_childUser","localField":"_id","foreignField":"telephone","as":"res"}},
{"$unwind":"$res"},
{"$group":{"_id":"$_id","total":{"$first":"$count"},"appName":{"$first":"$res.appName"},"province":{"$first":"$res.province"},
"city":{"$first":"$res.city"},"name":{"$first":"$res.nickName"},"createtime":{"$first":"$res.createTimestamp"}}},
{"$sort":{"createtime":-1}}
])
对应spring-data
Aggregation newAggregation = Aggregation.newAggregation(
Aggregation.match(new Criteria("telephone").ne(null)),
Aggregation.group("telephone"),
Aggregation.lookup("jg_orderInfo", "_id", "userTelephone", "data"),
Aggregation.unwind("data"),
Aggregation.group("_id").count().as("count"),
Aggregation.lookup("jg_childUser", "_id", "telephone", "res"),
Aggregation.unwind("res"),
Aggregation.group("_id").first("count").as("total").first("res.appName").as("appName").first("res.province").as("province")
.first("res.city").as("city").first("res.nickName").as("nickName").first("res.createTimestamp").as("createtime"),
Aggregation.sort(new Sort(new Order(Direction.DESC, "createtime")))
);
模糊查询:
{"$match":{"name":{"$regex":"^.*李.*$","$options":"i"}}};
$regex操作符的使用
$regex操作符中的option选项可以改变正则匹配的默认行为,它包括i, m, x以及S四个选项,其含义如下
i 忽略大小写,{<field>{$regex/pattern/i}},设置i选项后,模式中的字母会进行大小写不敏感匹配。
m 多行匹配模式,{<field>{$regex/pattern/,$options:'m'},m选项会更改^和$元字符的默认行为,分别使用与行的开头和结尾匹配,而不是与输入字符串的开头和结尾匹配。
x 忽略非转义的空白字符,{<field>:{$regex:/pattern/,$options:'m'},设置x选项后,正则表达式中的非转义的空白字符将被忽略,同时井号(#)被解释为注释的开头注,只能显式位于option选项中。
s 单行匹配模式{<field>:{$regex:/pattern/,$options:'s'},设置s选项后,会改变模式中的点号(.)元字符的默认行为,它会匹配所有字符,包括换行符(\n),只能显式位于option选项中。
使用$regex操作符时,需要注意下面几个问题:
i,m,x,s可以组合使用,例如:{name:{$regex:/j*k/,$options:"si"}}
在设置索弓}的字段上进行正则匹配可以提高查询速度,而且当正则表达式使用的是前缀表达式时,查询速度会进一步提高,例如:{name:{$regex: /^joe/}
Spring-data 实现:
new Criteria(key1).regex(Pattern.compile("^.*" + attrmap.get(key) + ".*$", Pattern.CASE_INSENSITIVE))
来源:https://www.cnblogs.com/mlorct/p/9223199.html