pom.xml 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
yml文件配置:
data:
mongodb:
port: 27017
host: xx.xx.xx.xx//(IP地址)
database: test
这里因为用nosql,非关系型数据库,所以只说明非实体类统计的用法,即,数据库中的表没有对应的实体类;
需求是:统计表中某列的总和
代码:
public Long getSumByScoreField(String name, String subject, String time) {
DBCollection collection = mongoTemplate.getCollection("user");//user为表
String matchStr = "{\"$match\":{\"name\":\"" + name+ "\",\"subject\":\"" + subject+ "\",\"login_time\":\"" + time + "\"}}";
String groupStr = "{\"$group\":{\"_id\": null,\"total\":{\"$sum\": \"$score\"}}}";
System.out.println(JSON.parse(matchStr));
DBObject match = (DBObject) JSON.parse(matchStr);
DBObject group = (DBObject) JSON.parse(groupStr);
LinkedList<DBObject> list= new LinkedList<>();
objects.add(match);
objects.add(group);
Cursor cursor = collection.aggregate(list, AggregationOptions.builder().outputMode(AggregationOptions.OutputMode.CURSOR).build());
while (cursor.hasNext()){
System.out.println(cursor.next());
}
}
以上代码中如果是第一次接触的同行就有一些陌生的关键字,如:$match,$group,$sum,这三个皆为对应mongodb的关键字,
match是依据的条件查询,group是分组查询,在该需求就会用到,sum聚合函数求总和,还有一个$score,这个是表中的字段score,因为要求和的正是该字段的和,固定写法而已,至于其他字段都是表的字段,注意这里没有对应的POJO类。
上述的代码中有这么一段代码:
Cursor cursor = collection.aggregate(list, AggregationOptions.builder().outputMode(AggregationOptions.OutputMode.CURSOR).build());
需要额外说明一下,这段代码之前我是这么写的:
AggregationOutput aggregate2 = collection.aggregate(match, group);
或者是:
AggregationOutput aggregate2 = collection.aggregate(list);
这么写的,很多时候在执行到这段代码的时候会出错,所以就改成上述代码段里的写法了因为当写成上面红色代码的两种方式时会报错:
com.mongodb.MongoCommandException: Command failed with error 9: 'The 'cursor' option is required, except for aggregate with the explain argument' on server 192.168.31.14:27017. The full response is { "ok" : 0.0, "errmsg" : "The 'cursor' option is required, except for aggregate with the explain argument", "code" : 9, "codeName" : "FailedToParse" }
at com.mongodb.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:115) ~[mongodb-driver-core-3.4.3.jar:na]
这种报错要么是依赖的mongodb版本和spring-bootstart版本不同,要么就是:这里细心的同行会发现,错误的(标红字)和正确的(代码段里面的)返回值类型不同,Cursor为输入模型的,AggregationOutput 为输出模型的,默认是输出模型,所以,当出现上述异常时可以改下代码为输入模型即可;
上述代码段还可以有一下写法:
public Long getSumByScoreField(String name, String subject, String time) {
BasicDBObject basicDBObject = new BasicDBObject();
// basicDBObject.put("name", name);
// basicDBObject.put("subject", subject);
// basicDBObject.put("update_time", time);
BasicDBObject[] basicDBObjects = {new BasicDBObject("name", name), new BasicDBObject("subject", subject), new BasicDBObject("update_time", time)};
// BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.put("$and", basicDBObjects);
BasicDBObject smatch = new BasicDBObject();
smatch.put("$match", basicDBObject);
BasicDBObject dbObject = new BasicDBObject("_id", null);
dbObject.put("total", new BasicDBObject("$sum", "$score"));
// DBObject group = new BasicDBObject("$group", dbObject);
List list = new LinkedList();
list.add(smatch);
list.add(group);
Cursor aggregate = collection.aggregate(list, AggregationOptions.builder().outputMode(AggregationOptions.OutputMode.CURSOR).build());
if (aggregate.hasNext()) {
System.out.println(aggregate.next().get("total"));
}
}
以上的两种写法最终翻译成mysql查询代码为:
select sum(score) as total from user where name=? and subject = ?and time=?
mongodb的写法为:
db.user.aggregate()
.match({"name":"JONE","subject":"数学","update_time":"2019-01-02"}).group({
_id: null,total:{$sum: "$score"}
})
如果是关系型,也就是创建对应表的实体类POJO的话就用:(这段代码还没测试,但大概思路、用法是这样的)
Aggregation aggregation = Aggregation.newAggregation(
match(Criteria.where("name").is(name).and("subject").is(subject).and("update_time").is(time)),
group("_id").sum("score").as("total"),
sort(Sort.Direction.DESC, "total"),
limit(1));
mongoTemplate.aggregate(aggregation,User.class,BasicDBObject.class);
补充--分组统计:
需求点:分组查询出选择不同班级,不同学科,不同时间报名中每组的总人数及总成绩
mysql:SELECT subject,DATE_FORMAT(sign_up_time,'%Y-%m-%d'),class_name,SUM(users_quantum) AS users_quantum,SUM(score)AS score FROM user
GROUP BY class_name,DATE_FORMAT(sign_up_time,'%Y-%m-%d'),subject
mongodb:aggregate([{$group: { _id: {class_name:"$class_name",subject:"$subject",sign_up_time:"$sign_up_time"},total:{$sum: "$score"},count:{$sum:1}}}])
注意:mongodb sql中双引号里面的自定义字段(除数据库聚合函数,即sql关键字之外的字段)必须加$符号
字段说明:subject-学科,class_name-班级名称,sign_up_time-报名时间,users_quantum-报名人数,score-成绩
以上纯属个人的一点开发实际来历,希望可以帮到见到的你,如有好的想法、方法。
请留言,谢谢!