# 概述 {#概述}
事情的起因要从最近的一个新产品说起,最近部门有一个新的大数据产品规划,在考虑技术实现时,有一个动态表字段扩展的需求,比如原来表结构里只有a、b字段,需要不断的往里新增c、d、e等等字段,并且数据量也特别大。
于是就去寻找实现方案,针对这种数据模型无法确定的情况,非关系型数据库是比较合适的,于是找到了MongoDB。虽然最后选择了使用ES来实现,但是在这段时间也把MongoDB摸了一遍,今天就分享一下。
# (一)MongoDB业务场景介绍 {#一-mongodb业务场景介绍}
一般在技术选型时,我们会把数据库的第一选择给Mysql,但是关系型数据库在某些场景下的效率和存储能力会不及非关系型数据库。比如:
对数据库有高并发操作或者对海量数据的高效存储和访问。但是MongoDB就可以很好的应对这些场景。
在技术选型时,如果遇到下面的情况:
- 数据量大
- 读写操作频繁
- 对事务等要求性不高
- 数据模型无法确定
- 需求中有大量的位置查询,文本查询
这个时候我们就可以选择使用MongoDB。
# (二)MongoDB介绍 {#二-mongodb介绍}
MongoDB是一个开源、高性能、无模式的文档型数据库,属于非关系型数据库的一种,MongoDB中的数据结构类似于JSON,它可以存储比较复杂的数据类型。MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
# (三)MongoDB基本增删改查 {#三-mongodb基本增删改查}
# 3.1 数据库操作 {#_3-1-数据库操作}
创建数据库:
use 数据库名
1
查看所有的数据库:
show databases
1
展示当前正在使用的数据库
db
1
删除数据库:
db.dropDatabase()
1
# 3.2 集合操作 {#_3-2-集合操作}
mongodb中的集合类似于关系型数据库中的表,在关系型数据库中,需要先创建表结构才能往里面写入数据,在mongodb中既可以先创建集合,也可以不创建集合,直接插入数据后自动创建集合。
主动创建集合方式:
db.createCollection("test")
1
查看集合:
show collections
1
删除集合:
db.test.drop()
1
# 3.3 文档操作 {#_3-3-文档操作}
文档就是关系型数据库中的数据了,文档的数据结构和JSON十分相似,在mongodb中被称为BSON。在插入时,可以指定文档的id:"_id:1",如果不指定就会自动生成一个id 单个文档插入:
db.test.insert(
{
"userName":"javayz",
"age":24
}
)
1
2
3
4
5
6
多个文档插入:
db.test.insertMany(
[
{
"userName":"javayz",
"age":24
},
{
"userName":"javayz2",
"age":24
}
]
)
1
2
3
4
5
6
7
8
9
10
11
12
普通文档查询:
#查询全部的文档
db.test.find()
#按条件查询文档
db.test.find({"age":24})
#投影查询,第一个JSON是查询条件,第二个JSON是展示字段,value为1表示展示,为0表示不展示
db.test.find({"age":24},{userName:1})
1
2
3
4
5
6
文档更新:
#第一个query是查询条件,第二个update是更新条件,第三个options是更新的一些参数
db.collection.update(query,update,options)
1
2
文档更新分为覆盖更新和局部更新,所谓覆盖更新,就是指更新之后会把整条数据覆盖;局部更新是指就更新某个字段。
覆盖更新:
通过下面的语句,会把test中对应id的文档变成只有age:25一个字段
db.test.update({_id:ObjectId("609419a54a3b1de79b6e4c5e")},{age:NumberInt(25)})
1
局部更新: 局部更新可以通过$set来实现,局部更新某一个字段
db.test.update({_id:ObjectId("609419a54a3b1de79b6e4c5f")},{$set:{age:NumberInt(25)}})
1
批量更新:
批量更新需要添加第三个options参数:
db.test.update({age:25},{$set:{userName:'aabb'}},{multi:true})
1
options还可以选填以下几个参数:
upsert 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern 可选,抛出异常的级别。
1
2
3
文档删除:
删除符合记录的文档:
db.test.remove({age:24}})
删除所有文档:
db.test.remove({})
1
2
3
4
文档统计:
统计可以通过count方法进行数量统计,query中可添加查询条件
db.test.count(query)
1
文档分页:
在需要展示的场景下就离不开分页,mongoDB提供了skip+limit的方式实现分页查询。比如下面这段逻辑实现每页十条进行分页:
db.test.find().skip(0).limit(10)
db.test.find().skip(10).limit(10)
db.test.find().skip(20).limit(10)
1
2
3
文档排序:
有分页就会有排序,通过sort实现排序效果,下面的操作实现对a字段升序,对b字段降序:
db.test.find().sort({a:1,b:-1})
1
# (四)文档复杂查询 {#四-文档复杂查询}
前面介绍了基本的增删改查操作,下面介绍一些相对复杂的查询操作。
# 4.1 正则查询 {#_4-1-正则查询}
mongoDB支持正则表达式查询,语法如下:
db.集合.find({字段:/正则表达式/})
1
比如要查询以aa开头的用户名:
db.test.find({userName:/^aa/})
1
# 4.2 比较查询 {#_4-2-比较查询}
比较查询用来实现小于、小于等于、大于、大于等于、不等于的操作,语法如下:
db.集合.find({字段:{$gt:value}}) 大于
db.集合.find({字段:{$gte:value}}) 大于等于
db.集合.find({字段:{$lt:value}}) 小于
db.集合.find({字段:{$lte:value}}) 小于等于
db.集合.find({字段:{$nt:value}}) 不等于
1
2
3
4
5
# 4.3 in查询 {#_4-3-in查询}
in用于实现包含查询:
db.test.find({userid:{$in:["001","002"]}})
1
不包含可以实用$nin实现。
# 4.4 条件查询 {#_4-4-条件查询}
条件查询用来实现and和or查询,在mongodb中通过$and和$or实现条件查询。
比如我想实现where age>24 and (userName='aa' or userName='bb')
,mongoDB实现如下:
db.test.find({$and:[{age:{$gt:24}},{$or:[{userName:"aa"},{userName:"bb"}]}]})
1
# (五)MongoDB索引 {#五-mongodb索引}
在Mysql中,如果数据量大的时候加索引和不加索引查询效率可能可以相差百倍,MongoDB也是。在没有索引的情况下MongoDB必须执行全集合扫描,针对集合中的字段适当添加索引可以极大地提高查询效率。MongoDB中索引使用B树结构。
MongoDB中提供了多种索引类型,常用的有单字段索引和复合索引,另外还支持地理空间索引、文本索引、哈希索引。
# 5.1 索引操作 {#_5-1-索引操作}
查看索引:
db.集合.getIndexes()
1
结果如下:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test"
}
]
1
2
3
4
5
6
7
8
9
10
其中key表示索引字段为_id,是升序索引;name表示索引名称是_id_;ns表示命名空间,是test这个库下的test集合里。
# 5.2 创建索引 {#_5-2-创建索引}
创建索引的语法如下:
db.集合.createIndex(keys, options)
1
比如创建一个复合索引,通过age升序,name降序:
db.test.createIndex({"age":1,"name":-1})
1
options为可选字段:
# 5.3 删除索引 {#_5-3-删除索引}
可以删除指定的索引或者所有索引,不指定index就是删除所有索引:
db.集合.dropIndex(index)
1
其中index中的内容可以索引的名称也可以是索引的规范:
db.test.dropIndex({"age":1,"name":-1})
1
# (五)总结 {#五-总结}
MongoDB曾经在国内火了一阵,但是随着后来MySQL、ElasticSearch、Redis以及后来的大数据崛起,使用这款数据库的公司越来越少,但是这款数据库依旧有它的价值所在。我是鱼仔,我们下期再见!