阅读 847
结合单表SQL快速学习Mongo操作语法

结合单表SQL快速学习Mongo操作语法

前言

MongoDB是目前非常主流的非关系型数据库,松散的数据结构(json和bson)便于存储复杂的数据类型,强大的查询语法(具备关系型数据库单表查询的大部分功能),支持创建索引,查询性能优。对于MongoDB的数据存储和MySQL数据库存储,单条数据可以看作是一个Map<String,Obect>和一个实体对象的区别,MongoDB可以随意存放各种字段及数据类型,MySQL需要插入在表设计时候定义好的数据字段及类型,在适用的场景下,这是MongoDB等非关系型数据库的一大优势。

知识点

  • 简单查询(条件查询、分页查询、排序、操作符使用)
  • 分组聚合(单字段分组、多字段分组)
  • 更新、删除

查询

演示数据

user_info

姓名(name)年龄(age)性别(sex)住址(address)体重(weight)
卡戴珊29洛杉矶60
乔治30洛杉矶80
布克23菲尼克斯80
东契奇23达拉斯80

注意:name是MySQL关键字,实际开发中不要使用关键字作为字段名

简单查询

1 查询详细信息

select name, age, sex,address from user_info where name = '布克' limit 1;
复制代码
db.user_info.find({"name":"布克"},{"name":1,"age":1,"sex":1, "address":1}}).limit(1);
复制代码

1.1 多字段匹配

select name, age, sex,address from user_info where name = '布克' and address = '菲尼克斯' limit 1;
复制代码
db.user_info.find({"name":"布克", "address":"菲尼克斯"},{"name":1,"age":1,"sex":1, "address":1}}).limit(1);
复制代码

Monogo查询使用find()方法,find方法包含两个参数均为json结构,第一个参数是查询条件,第二个是指定需要查询的键,值为0代表不查询此字段,1代表查询此字段,此条mongo查询涉及两个方法find(query, projection),limit(size),对应mysql中的select和limit,区别在于mysql中limit可以包含offset参数及limit参数,下面展示mongo中如何实现mysql分页中的limit双参数写法,find的第一个参数填写空的json({})代表的是查全表,第二个参数填空json({})代表的是获取所有字段

db.user_info.find({},{})或db.user_info.find() = select * from user_info

2 分页查询

select name, age, sex,address,weight from user_info limit 1,1;
复制代码
db.user_info.find({},{"name":1,"age":1,"sex":1, address":1,"weight":1}).limit(1).skip(1)
复制代码

MongoDB要实现从第多少条往后查询多少条需要将limit方法和skip方法组合使用,MySQL中的有limit更有弹性

3 排序查询

3.1 单字段排序

SELECT name,age,sex,address,weight FROM `user_info` ORDER BY age desc
复制代码
db.user_info.find({},{"name":1,"age":1,"sex":1, "address":1}).sort({"age":-1})
复制代码

mysql中使用order by 字段 进行排序(可以置顶升序asc、降序desc,不指定则默认降序),mongo中使用sort({"key": -1或1})进行排序,-1为降序、1为升序

3.2 多字段排序

SELECT name,age,sex,address,weight FROM `user_info` ORDER BY age desc,weight asc
复制代码
db.user_info.find({},{"name":1,"age":1,"sex":1, "address":1,"weight":1}).sort({"age":-1,"weight":1})
复制代码

4 模糊查询

SELECT name,age,sex,address,weight FROM `user_info` where address like '%洛%';
复制代码
db.getCollection('user_info').find({"address":{'$regex':'洛'},{"name":1,"age":1,"sex":1,"address":1,"weight":1})
复制代码

$regex相当于是一个简化的正则判断,Mongo查询规则主要为以xx开头或结尾,包含xx,是否区分大小写

5 常用条件操作符

条件操作符描述示例
$ne不等于db.getCollection('user_info').find({"age":{'$ne':23}})
$lt小于同上
$gt小于等于同上
$gt大于同上
$gte大于等于同上
$ordb.getCollection('user_info').find({"$or":{'name':'布克','age':29}}
$nor或取反同上
$inin查询db.getCollection('user_info').find({'name':{'$in':['布克','卡戴珊']}})

5.1 组合使用示例

大于23岁小于等于30岁
db.getCollection('user_info').find({"age":{'$gt':23,'$lte':30}};
年龄在23到30,住在洛杉矶、达拉斯的人
db.getCollection('user_info').find({"age":{'$gt':23,'$lte':30}, 'address':{'$in':['洛杉矶','达拉斯']}};
复制代码

简单查询总结

简单查询部分介绍了我们常用的条件查询,分页查询,条件操作符的应用,熟练掌握上面的命令就能够在开发中对数据进行常规的查询操作,下面介绍一下Mongo聚合分组查询的应用。

分组聚合

难点

mongo分组聚合的语法单独拿出来并不难,但是在结合了复杂条件,起别名后就会层级比较多,建议先熟练简单的分组,使用json编辑器进行编辑,能够清楚看清层级关系,便于自己理解

单字段分组

按address分组统计大于18岁的总体重(单字段分组)

SELECT address, SUM(weight) weightSum FROM `user_info` where age >=18 GROUP BY address
复制代码
db.user_info.aggregate([{"$match":{"age":{"$gte":18}}},{"$group":{"_id":"$address","weightSum":{"$sum":"$weight"}}}])
复制代码

image.png

mongo分组聚合使用aggregate方法,mongo的每一条数据会有一个唯一的_id,会在插入时候自动生成,也可以在插入的时候手动设置

image.png

  • aggregate方法参数为数组[{},{}]
  • 数组第一个元素格式固定为{"$match":{}},key就是匹配操作符,值对应的就是简单查询中的条件比如 {"$match":{"address":"洛杉矶"}}就是sql group前的where address = "洛杉矶"
  • 第二个参数格式为{"$group":{}},$group是mongo中的分组操作符,值中如果按照address分组,就是_id:"$address",然后就是分组后要做的聚合操作,可以相当于别名,值也是一个json,值得json key就是函数,value就是$+统计的字段

多字段分组

按address和性别分组统计平均体重(多字段分组)

db.user_info.aggregate([{"$match":{"age":{"$gte":18}}},{"$group":{"_id":["$address","$sex"],"weightSum":{"$avg":"$weight"}}}])
复制代码

区别就是分组中_id对应的值变成多个字段分组字段的数组,返回值中_id也相应的变成数组

image.png

删除

delete from user_info where name = '布克' limit 1;
复制代码
db.collection.remove(
   {'name':'布克'},
   ture
)
复制代码

mongo删除使用remove方法,方法第一个参数为删除条件,与find的查询条件语法相同,第二个参数为是否删除一个,true就只会删除条件匹配到的第一个数据

新增

insert into user_info(name, age, address, sex) values("保罗","36","菲尼克斯","男")
复制代码
db.user_info.insert({"name":"保罗","age":"36","address":"菲尼克斯","sex":"男"})
复制代码

mongo插入语句也是insert,插入一条数据为一个json结构,key就是字段名称, value就是值,mongo集合中每条数据相同的字段名可以是不同的类型,这也是灵活的体现,但是不推荐这样使用,不便于维护

更新

mongo更新方法很强大,update方法包含四个参数,第一个为条件(格式为{}),第二个为更新的值(格式为{'$set':{'字段':'值'}),第三个为upsert(存在符合条件的即更新,不存在即插入,默认false),第四个为是否更新多个(默认fasle只更新符合条件的第一个)

更新卡戴珊的住址

update user_info set address="纽约" where name = "卡戴珊" limit 1;
复制代码

ps:mysql中更新插入的方法有很多,比如replace into会根据数据中的主键或者唯一索引检查数据是否存在,存在情况会导致自增id发生改变,需要慎用

db.user_info.update({"name":"卡戴珊"},{"$set":{"address":"纽约","telephone":10086}},true, false)
复制代码

可以看到我在更新卡戴珊的时候,还添加了一个之前不存在的字段telephone,这样卡戴珊的个人信息就会多出一个telephone,这也是MongoDB松散的体现

最后

本文涉及了开发中常用的简单查询及分组聚合,覆盖了绝大多数场景,通过与sql的对比快速学习mongo操作,希望能够帮助到有需要的人

点击学习MongoDB分表

分分钟学会MongoDB GridFs搭建文件服务

了解一下Redis缓存及本地缓存设计实践

文章分类
后端
文章标签