为什么需要NoSQL,可以应付超大规模,高并发;传统数据库的性能和扩展瓶颈;解决大规模数据集合、多重数据种类的挑战;大数据应用难题,包括超大规模数据的存储。
| 分类 | 优势 | 劣势 | 场景 | 代表 |
|---|---|---|---|---|
| 键值对 | 查找速度快 | 数据无结构化,通常只被当做字符串或者二进制数据 | 内容缓存,大量数据的高频访问 | redis |
| 列式存储 | 查找速度快,支持分布式横向扩展,数据压缩率高 | 功能相对受限 | 分布式文件系统 | HBASE,cassandra |
| 文件存储 | 数据结构要求不严格,表结构可变 | 查询性能不高,缺乏统一的查询语法 | web应用 | mongodb |
| 图数据库 | 可利用图结构相关算法 | 可能需要对整个图做计算,不利于图数据分布式存储 | 社交网络、推荐系统、意向图、消费图、兴趣图、关系图谱等 | Neo4j,couchDB |
Mongodb:是一个机遇c++开发的NoSQL开源文档数据库,具有所需的可伸缩性和灵活性,可用于所需的查询和索引编制。最像关系数据库,功能丰富的NoSQL数据库。
| 特性 |
|---|
| 面相机和文档的存储:适合存储Bson(json的扩展)形式的数据 |
| 格式自由,数据格式不固定,生产环境下修改结构都不影响程序运行 |
| 强大的查询语句,面向对象的查询语言,基本覆盖sql语言所有能力 |
| 完成的索引支持,支持查询计划 |
| 支持复制和自动故障转移 |
| 支持二进制数据及大型对象(文件)的高效存储 |
| 使用分片集群提升系统扩展性 |
| 使用内存映射存储引擎,把磁盘的IO操作转换成为内存的操作。 |
| 应用需求场景 |
|---|
| 不需要事务及复杂的join支持 |
| 新应用,需求会变,数据模型不确定,想快速迭代开发 |
| 要求对2000-3000以上的读写QPS |
| 要存储TB甚至PB级别数据 |
| 应用发展迅速,能快速水平扩展 |
| 要求存储数据不丢失 |
| 要求99.999%高可用 |
| 有大量的地理位置查询,文本查询 |
MongoDB vs 关系型数据库
| --- | MongoDB | RDBMS |
|---|---|---|
| 数据模型 | 文档模型(json对象) | 关系模型 |
| 数据库类型 | OLTP | OTLP |
| CRUD操作 | MSQ/SQL | SQL |
| 高可用 | 复制集 | 集群模式 |
| 横向扩展能力 | 通过原声分片完善支持 | 数据分区或者应用侵入式 |
| 索引支持 | B树、全文索引、地理位置索引、多键(multikey)索引、TTL索引 | B树 |
| 开发难度 | 容易(应用程序代码、建模非常容易) | 难 |
| 数据容量 | 没有理论上限 | 千万、亿 |
| 扩展方式 | 垂直扩展+水平扩展 | 垂直扩展 |
关系模型 VS 文档模型
| --- | 关系数据库 | JSON文档模型 |
|---|---|---|
| 模型设计层次 | 概念模型 逻辑模型 物理模型 |
概念模型 逻辑模型 |
| 模型实体 | 表 | 集合 |
| 模型属性 | 列 | 字段 |
| 模型关系 | 关联关系,主外键 | 内嵌数组,引用字段 |


| 软件模块 | 描述 |
|---|---|
| mongod | mongodb数据库软件 |
| mongo | mongodb命令行工具,管理mongodb数据库 |
| mongos | mongodb路由进程,分片环境下使用 |
| mongodump/mongorestore | mongodb备份恢复工具 |
| mongoexport/mongoimport | csv/json导入导出,主要用于不同系统间数据迁移 |
| compass | mongodb GUI 管理工具 |
| Ops Manager(企业版) | MongoDB集群管理软件,升级、扩容、监控告警、持续备份与恢复、k8s集成等功能 |
| BI Connectoir(企业版) | MongoDB可视化软件,兼容mysql语法,在例如powerbi 与mongodb中间做查询与结果转换(不支持写入) |
| Atlas(付费及免费) | MongoDB云托管服务,包括永久免费云数据库 |
| MongoDB Charts | 可视化分析,创建图表 |
Mongodump/mongorestore : 类似Mysql的dump/restore工具;可以完成全库dump:不加条件; 也可以根据条件dump部分数据:-q参数;Dump的同时跟踪数据更新:--oplog; Restore是反操作,把mongodump的输出导入到mongodb.
mongodump -h 127.0.0.1:27017 -d test -c test
mongorestore -h 127.0.0.1:27017 -d test -c test xxx.bson
官网下载地址:https://www.mongodb.com/try/download.(可以在cloud.mongodb.com上申请一个免费的mongodb集群使用,这里不介绍)
#centos7 通过yum安装
[root@localhost ~]# vim /etc/yum.repos.d/mongodb.repo
[mongodb-org-4.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc
[root@localhost ~]# yum install -y mongodb-org
[root@localhost ~]# systemctl enable mongod
##修改监听的ip地址从127.0.0.1改为0.0.0.0
[root@localhost ~]# vim /etc/mongod.conf
net:
port: 27017
bindIp: 0.0.0.0
[root@localhost ~]# systemctl start mongod
基本连接使用
| 基本命令 | 解释 |
|---|---|
| use databaseName; | 如果databaseName不存在,在插入数据时会创建数据库 |
| show dbs | 显示当前实例中的数据库 |
| db.dropDatabase() | 删除当前数据库 |
| db.createCollection("test) | 显示创建test集合 |
| show tables | 显示当前数据库中的集合信息 |
| show collections | 同上 |
| db.test.drop() | 删除test集合 |
[root@localhost ~]# mongo
> show dbs;
admin 0.000GB
config 0.000GB
local 0.000GB
> use testdb
switched to db testdb
> db.users.insert({name:'hash',age:18,lenth:18,lover:'keke'})
WriteResult({ "nInserted" : 1 })
> show tables;
users
> show collections;
users
> show dbs;
admin 0.000GB
config 0.000GB
local 0.000GB
testdb 0.000GB
[root@localhost ~]# tar xf dump.tar.gz
[root@localhost ~]# ls dump
mock
[root@localhost ~]# mongorestore dump
############查看测试数据
[root@localhost ~]# mongo
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
mock 0.047GB
testdb 0.000GB
> use mock
switched to db mock
> show collections
orders
> db.orders.findOne()
{
"_id" : ObjectId("5dbe7a545368f69de2b4d36e"),
.................................省略部分输出
}
图形化客户端compass使用,完全免费;windows下载后解压运行MongoDBCompass。 这里只演示无认证登陆。(下载地址:https://downloads.mongodb.com/compass/mongodb-compass-1.26.1-win32-x64.zip)

insert 插入数据,格式如下:
| 操作格式 | 命令 | 例子 |
|---|---|---|
| 单个json对象插入 | db.<集合>.insertOne( |
db.fruit.insertOne({name:"apple"}) |
| 多个json对象插入 | db.<集合>.insertMany([ |
db.fruit.insertMany([{name:"apple"},{name:"pear"},{name:"orange"}]) |
##insertedId 是mongodb提供的默认主键,字段名是_id
> db.fruit.insertOne({name:"apple"})
{
"acknowledged" : true,
"insertedId" : ObjectId("608a09b871cb09186460d9b8")
}
> db.fruit.insertMany([{name:"apple"},{name:"pear"},{name:"orange"}])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("608a0ab571cb09186460d9b9"),
ObjectId("608a0ab571cb09186460d9ba"),
ObjectId("608a0ab571cb09186460d9bb")
]
}
使用find查询文档,find是mongodb中查询数据的基本指令,相当于SQl中的select. find返回的是游标。
| find示例 |
|---|
| db.movies.find({"year":1975}) //单条件查询 |
| db.movies.find({"year":1975,"title":"Batman"}) //多条件and查询 |
| db.movies.find({$and:[{"year":1975},{"category":"action"}]}) //and的另一种形式 |
| db.movies.find({$or:[{"year":1997},{"title":"Batman"}]}) //多条件or查询 |
| db.movies.find({"title":"/^B/"}) //按正则表达式查找 |
| SQL | MSQL |
|---|---|
| a=1 | {a:1} |
| a<>1 | {a:{$ne:1}} |
| a>1 | {a:{$gt:1}} |
| a>=1 | {a:{$gte:1}} |
| a<1 | {a:{$lt:1}} |
| a<=1 | {a:{$lte:1}} |
| a=1 and b=1 | {a:1,b:1} 或者 {$and:[{a:1},{b:1}]} |
| a=1 or b=1 | {$or[{a:1},{b:1}]} |
| a is null | {a:{$exists: false}} |
| a in (1,2,3) | {a:{$in:[1,2,3]}} |
| $nin:不存在或不在指定的数组中 | |
| $ne: 不存在或存在但不等于 |
> db.fruit.find()
{ "_id" : ObjectId("608a09b871cb09186460d9b8"), "name" : "apple" }
{ "_id" : ObjectId("608a0ab571cb09186460d9b9"), "name" : "apple" }
{ "_id" : ObjectId("608a0ab571cb09186460d9ba"), "name" : "pear" }
{ "_id" : ObjectId("608a0ab571cb09186460d9bb"), "name" : "orange" }
使用find搜索子文档
##find支持使用field.sub_field的形式查询子文档。假设有一个文档:
db.fruit.insertOne({
name:"apple",
from:{
country:"China",
province:"Guangdong"
}
})
##查询子文档,要在双引号里面写文档的路径"from.country", 第二种写法查询不到结果
> db.fruit.find({"from.country":"China"})
{ "_id" : ObjectId("608a117871cb09186460d9bc"), "name" : "apple", "from" : { "country" : "China", "province" : "Guangdong" } }
> db.fruit.find({"from":{country:"China"}})
>
使用find搜索数组(下面color是个数组)
> db.fruit.insert([{"name":"Apple",color:["red","green"]},{"name":"Mango",color:["yellow","green"]}])
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
> db.fruit.find({color:"red"})
{ "_id" : ObjectId("608a12c271cb09186460d9bd"), "name" : "Apple", "color" : [ "red", "green" ] }
> db.fruit.find({$or:[{color:"red"},{color:"yellow"}]})
{ "_id" : ObjectId("608a12c271cb09186460d9bd"), "name" : "Apple", "color" : [ "red", "green" ] }
{ "_id" : ObjectId("608a12c271cb09186460d9be"), "name" : "Mango", "color" : [ "yellow", "green" ] }



remove删除文档: remove命令需要配合查询条件使用,匹配查询条件的文档会被删除;指定一个空文档条件会删除所有文档;
###示例:
db.testcol.remove({a:1})//删除a等于1的记录
db.testcol.remove({a:{$lt:5}})//删除a小于5的记录
db.testcol.remove({})//删除所有记录
db.testcol.remove()//报错
使用update更新文档

drop删除集合: 使用db.<集合>.drop()来删除一个集合,集合中的全部文档都会被删除,集合相关的索引也会被删除。
db.colToDeDropped.drop()
[root@localhost ~]# pip3 install pymongo
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting pymongo
Downloading https://files.pythonhosted.org/packages/03/4b/2adf815a054b467e87de2b5c830dfc9bc75e9ae7f977b50e6bb8eca7c3ac/pymongo-3.11.3-cp36-cp36m-manylinux1_x86_64.whl (492kB)
100% |████████████████████████████████| 501kB 455kB/s
Installing collected packages: pymongo
Successfully installed pymongo-3.11.3
[root@localhost ~]# python3
Python 3.6.8 (default, Nov 16 2020, 16:55:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymongo
>>> pymongo.version
'3.11.3'
>>> from pymongo import MongoClient
>>> uri="mongodb://192.168.52.129:27017"
>>> client= MongoClient(uri)
>>> print(client)
MongoClient(host=['192.168.52.129:27017'], document_class=dict, tz_aware=False, connect=True)
>>> db=client['eshop']
>>> user_coll=db['users']
##测试数据库还没有真正创建
>>> new_user={"username":"nina","password":"xxx","email":"11234@qq.com"}
>>> result=user_coll.insert_one(new_user)
>>> print(result)
<pymongo.results.InsertOneResult object at 0x2ba421f0fac8>
更新用户,增加字段phone
###python代码
>>> result = user_coll.update_one({"username":"nina"},{"$set":{"phone":"123456789"}})
>>> print(result)
<pymongo.results.UpdateResult object at 0x2ba421f29708>
###mongo下
> use eshop
switched to db eshop
> db.users.find()
{ "_id" : ObjectId("608a2e73cb2ff42ea94f7e57"), "username" : "nina", "password" : "xxx", "email" : "11234@qq.com", "phone" : "123456789" }
参考视频资料:https://www.bilibili.com/video/BV17V411n7q9?p=11&spm_id_from=pageDriver 参考视频资料:https://space.bilibili.com/441067951/video