mongodb分享(二)
上次讲的:查询 find\findone\pretty、条件操作符 (大于、小于、大于等于、小于等于、不等于,$type)、limit\skip、sort、Db.postjson.getIndexes();
$type:$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
BSON类型: 一种增强型的 JSON 格式,比 JSON 数据类型多,是 Binary JSON 的简称。特点:解释更快。
https://blog.csdn.net/leshami/article/details/52668870
https://www.runoob.com/mongodb/mongodb-operators-type.html
上次遗留问题: mongodb 与 mysql 的区别?为什么用 mongdb 而不用 mysql?
1)mongodb 支持自动分片,方便帮集群添加和删除节点。对应用程序而言,好像始终在使用一个单机有 mongodb 服务器一样。它会自动处理数据在数据在分片上的分布,而 mysql 不行,mysql 在增加集群节点时,需要人工分表,做数据迁移。
2 ) mongodb 可以随意扩展字段,需要增加字段时很轻松就加进去了,而 mysql 增加字段还需要改表结果,所以 mongodb 适合存储这种非结构化的信息。
聚合:aggregate 管道聚合:pipeline aggregate
1 。group by
db.postjson.aggregate([{$group:{_id:"$bwHotelID",reviewcnt:{$sum:1}}}]);
这里的$sum:1 相当于count(*) 要对某个字段进行sum 应写成 $sum : “$字段名”
2。 group by + where
db.postjson.aggregate([{$group:{_id:"$bwHotelID",reviewcnt:{$sum:1}}},{$match:{bwHotelID:284500}}]);
db.postjson.aggregate([{$group:{_id:"$bwHotelID",reviewcnt:{$sum:1}}},{$match:{_id:160733}}]);
db.postjson.aggregate([{$match:{bwHotelID:160733}}]);
这里的$match就相当于sql语法中的where
3。group by + 字段筛选
db.postjson.aggregate([{$group:{_id:"$bwHotelID",reviewcnt:{$sum:1}}},{$project:{_id:0,reviewcnt:1}}]);
db.postjson.aggregate([{$group:{_id:"$bwHotelID",reviewcnt:{$sum:1}}},{$project:{_id:0,reviewcnt:1}},{$match:{reviewcnt:4}}]);
db.postjson.aggregate([{$group:{_id:"$bwHotelID",reviewcnt:{$sum:1}}},{$project:{_id:0,reviewcnt:1}},{$match:{reviewcnt:{$ne:4}}}]);
条件操作符在match中仍然可以用。 $gt $lt $gte $lte $ne $in
4. group by + where + 字段筛选 + having
- sum
- avge
- min
- max
- push 在结果文档中插入值至一个数组 ???
- addToSet ????
- first
- last
管道聚合: 语法:db.collection.aggregate(pipeline, options)
1) project 字段筛选 及字段重命名。
2) match where
3) limit limit
4) skip skip
5) unwind
6) group group by $group语法: {$group: { _id: <expression>, <field1>: { <accumulator1> : <expression1>}, ... } }
7) sort order by
8) geoNear
https://blog.csdn.net/congcong68/article/details/51619882
https://blog.csdn.net/congcong68/article/details/51620040
注:group: 如果_id为null 相当于select count(*) from table
mongodb 权威指南.pdf p129
7.1 聚合框架:
聚合框架中的操作符:
1)$project
2) $group
3) $sort
4) $limit
7.2 管道操作符
1)$match
2)$project ( 提取字段、重命名字段、对字段进行操作)
管道表达式:
数学表达式: $add、$subtract $multiply $divide $mod
日期表达式: $month、$week、$dayOfMonth、$dayOfWeek、$dayOfYear、$hour、$minute、$second
字符串表达式:$substr、$concat、$toLower、$toUpper
逻辑表达式:$cmp、$strcasecmp、$gt、$lt、$gte、$lte、$ne、$eq、$in、$nin、$and、$or、$not、$cond、$ifNull
3) $group
group by a,b ====={"$group":{"_id":{a:$a,b:$b}}}
分组操作符:
算术操作符:$sum、$avg
极值操作符: $max、$min、$first、$last
数组操作符: $addToSet、$push
4)$unwind
5) $sort
6) $limit
7) skip
8) 使用管道 :
============mongodb 某个字段模糊匹配中文 =============
{"hotelname":{'$regex':'派酒店廊坊香河家'}}
第一种:使用 $regex 第二种:使用 / 钟 / 两种均可,个人觉得还是加 / 敏 / 的这种更简单。
- >db.posts.find({post_text:{$regex:"shouce.ren"}}) {'source_hotel_id':'4056562','room_name':{$regex:'钟'}}
- >db.posts.find({post_text:/shouce.ren/}) {'source_hotel_id':'4056562','room_name':/ 钟 /}
- 查手册《mongodb 参考手册 - 新》
===== 查询价格计划名称中包含“小时”两个字,但不包含“钟点房”三个字的正则。============
mongodb 中的 $unwind 管道聚合
需求:
{ "_id" : ObjectId("5951c5de567ebff0d5011fba"), "name" : "陈晓婵", "address" : "北京朝阳区", "weekday" : [ 1, 2, 3, 4, 5 ] }
对 weekday 进行拆分:
db.getCollection('chenxiaochantest').aggregate( [ { $unwind:"$weekday" } ] )
拆分结果:
/* 1 */ { "_id" : ObjectId("5951c5de567ebff0d5011fba"), "name" : "陈晓婵", "address" : "北京朝阳区", "weekday" : 1 }/* 2 */
{
"_id" : ObjectId("5951c5de567ebff0d5011fba"),
"name" : "陈晓婵",
"address" : "北京朝阳区",
"weekday" : 2
}/* 3 */
{
"_id" : ObjectId("5951c5de567ebff0d5011fba"),
"name" : "陈晓婵",
"address" : "北京朝阳区",
"weekday" : 3
}/* 4 */
{
"_id" : ObjectId("5951c5de567ebff0d5011fba"),
"name" : "陈晓婵",
"address" : "北京朝阳区",
"weekday" : 4
}/* 5 */
{
"_id" : ObjectId("5951c5de567ebff0d5011fba"),
"name" : "陈晓婵",
"address" : "北京朝阳区",
"weekday" : 5
}
使用 $unwind 可以将 weekday 中的每个数据都被分解成一个文档, 并且除了 weekday 的值不同外, 其他的值都是相同的.
实例讲解:
{ "_id" : ObjectId("5951ca15567ebff0d5011fbb"), "name" : "陈晓婵", "address" : "北京朝阳", "lunch" : [ { "food" : "baozi", "fruit" : "taozi" }, { "food" : "miaotiao", "fruit" : "xigua" } ] }
对 lunch 进行拆分:
db.getCollection('chenxiaochantest2').aggregate( [ { $unwind:"$lunch" } ] )
拆封结果:
/* 1 */ { "_id" : ObjectId("5951ca15567ebff0d5011fbb"), "name" : "陈晓婵", "address" : "北京朝阳", "lunch" : { "food" : "baozi", "fruit" : "taozi" } }/* 2 */
{
"_id" : ObjectId("5951ca15567ebff0d5011fbb"),
"name" : "陈晓婵",
"address" : "北京朝阳",
"lunch" : {
"food" : "miaotiao",
"fruit" : "xigua"
}
}
转载来源:https://blog.csdn.net/chenxiaochan/article/details/73771879
关于 mongodb 根据时间统计 (日、月、年),数据库 ISODate 与当前差了 8 小时时区的解决方案
1,问题:
在做数据统计时,有需求根据时间做统计,然而数据库里存的是 ISODate 格式,之前单纯的通过 $dateToString 的方式做了个时间格式转换,后来发现是有问题的,由于 ISODate 的时区和我们本地时区差了 8 小时,也就是说明明是同一天的会被当成 2 天来统计
例:2019-04-26 9 点 =ISO 格式 2019-04-26 1 点
2019-04-26 5 点 =ISO 格式 2019-04-25 21 点
这样明明是同一天的数据就变成了 2 天的数据了,
后来在网上找到了解决方法
2:方案代码
在 group 统计之前先对日期数据进行 8 小时时区的增加 (使用 $add 方法),然后再根据转义后的时间进行统计
例:
数据库写法(已测试):{$project:{ "newDate":{ $add : ["$createDate", 28800000]} }}// 加 8 小时
java 后台 DBObject 写法(已测试):
// 处理 ISODATE
String parseIso="{\n"+
"\"$project\": {\n"+
"\"newDate\": {\n"+
"\"$add\": [\"$happenTime\", 28800000]\n"+
"}\n"+
"\"alertLevel\":\"$alertLevel\""+
"}\n"
"}";
DBObject parseIsoProject = (DBObject) JSON.parse(parseIso);
java 后台 AggregationOperation 的 ProjectionOperation 写法(未测试):
Aggregation.project().andExpression("add(createTime," + 8 * 60 * 60 * 1000 + ")").as("newDate");
3:思路
其实很简单,就是在统计之前对时区先做好处理,让他变成当前时间即可,部分未测代码也是网上找来的,可根据实际情况调试