为什么需要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