目录
前言:
大家都知道,mongodb是一个非关系型数据库,也就是说,mongodb数据库中的每张表是独立存在的,表与表之间没有任何依赖关系。当我们数据量非常大时,都通过筛选条件去筛选不尽人意;所以,我们设计的时候,就直接通过DB进行区分,如:聊天记录,通过roomId建DB等。在mongodb中,除了各种CRUD语句之外,还给我们提供了聚合的功能,这篇文章主要来跟大家聊聊mongodb的aggregate的操作。
应用场景:
最近因开发直播项目,用MongoDB存储用户聊天数据,后期数据量会非常大。处理好数据结构,每天处理上亿的数据没问题,小编以前就用Mongodb存储路由器访问记录数据,每天过亿。
MongoDB 是一种文档型数据库,里面分为数据库(DBs)和集合(Collections),分别相当于SQL的数据库和数据表。数据因为本次业务原因,做的都是查询操作,没有增删改等操作。
命令描述:![](https://i-blog.csdnimg.cn/blog_migrate/fb53e576a1f07d6fa1a64a054866bb06.png)
管道的概念:
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。
这里我们介绍一下聚合框架中常用的几个操作:
● $project:(select)修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
● $match:(where)用于过滤数据,只输出符合条件的文档。 $match使用MongoDB的标准查询操作。
● $group:(group by)将集合中的文档分组,可用于统计结果。
● $match:(having)。
● $sum:(sum)可用于统计结果。
● $sum $sortByCount:(count)可用于统计数。
● $lookup:(join)建立连接。
● $limit:(limit)用来限制MongoDB聚合管道返回的文档数。
● $skip:(偏移量)在聚合管道中跳过指定数量的文档,并返回余下的文档。
● $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
● $sort:(order by, 1升序,-1降序)将输入文档排序后输出。
● $geoNear:输出接近某一地理位置的有序文档。
代码示例:
需要注意的是,MongoDB有一个管道的概念,相当于一层一层的过滤,顺序不能乱,否则会报错(A pipeline stage specification object must contain exactly obe field)。这其实和我们在用sql语句查询时候是一样的,都是select.....where....group by....order by....limit...顺序不能乱是一样的。
聚会查询:
// match(相当于 WHERE 或者 HAVING )
BasicDBObject query= new BasicDBObject();
BasicDBObject[] array = { new BasicDBObject("time", new BasicDBObject("$gte", "2018-09-12")),new BasicDBObject("time", new BasicDBObject("$lte","2018-12-25"))};
query.append("$and", array);
BasicDBObject match = new BasicDBObject("$match", query);
// group(相当于 GROUP BY)
BasicDBObject group = new BasicDBObject("$group", new BasicDBObject("_id", "$subject")
.append("count", new BasicDBObject("$sum", 1)));
// sort(排序)
BasicDBObject sort = new BasicDBObject("$sort", new BasicDBObject("count", -1));//1:正序,-1倒序
// skip(跳过前面多少条数据,分页时使用)
//limt(只要前多少条数据,分页时使用)
BasicDBObject limit = new BasicDBObject("$limit", pageSize);
BasicDBObject skip = new BasicDBObject("$skip", (pageNo - 1) * pageSize);
// queryList集合里的**顺序不能乱**,否则会报错。
List<DBObject> queryList = new ArrayList<>();
queryList .add(match);
queryList .add(group);
queryList .add(sort);
queryList .add(skip);
queryList .add(limit);
// 变量dbName,动态指向DB
AggregateIterable<Document> iterable = mongoClient.mongoClient.getDatabase(dbName).getCollection(gatherName).aggregate(queryList );
上面的代码就是进行聚合后的操作,查询出的集合里有(_id,count)两个字段,_id对应的值就是subject,count对应的值是总数,这样我们就可以查出结果了,并且进行了分页操作,只需要传入相应pageNo和pageSize就可以了。
数量查询:
由于我们设计的时候,是通过房间为维度roomID作为DB(变量DBName),查询数量可以通过以下方式:
// 获取聊天总数
Long count = mongoTemplate.getCollection(DBName).countDocuments();
如果本篇文章对你有帮助的话,很高兴能够帮助上你。
当然,如果你觉得文章有什么让你觉得不合理、或者有更简单的实现方法又或者有理解不来的地方,希望你在看到之后能够在评论里指出来,我会在看到之后尽快的回复你。