什么是NoSQL?
NoSQL,指的是非关系型的数据库(Not only sql)。
没有行、列的概念。用 JSON 来存储数据。集合就相当于 SQL 数据库中的“表”,文档就相当于“行”。
- 数据模型比较简单;
- 需要灵活性更强的IT系统;
- 对数据库性能要求较高;
- 不需要高度的数据一致性;
- 对于给定key,比较容易映射复杂值的环境。
NoSQL有哪些
memcache、mongodb、redis、ElasticSearch、hbase、PostgreSQL等
mongodb和传统关系型数据库的应用场景区别
mongodb适合做原始数据的归档,以备供大量数据查询。而高级的统计、汇总之类的,mongodb支持相对较弱。事物处理能力低。
mongodb 和 redis
mongo存放东西是放在硬盘上的,redis是放在内存里面的,当然redis也会定期持久化到磁盘上,mongo比较适合大数据,redis适合数据量小,但是效率要求很高的场合。
基本概念
部署安装
官网下载tar包,解压后即可使用绿色软件。
配置文件,新建etc/mongodb.conf:
dbpath=/data/mongodb/master
logpath=/data/mongodb/log/master.log
master=true
fork=true
port=27017
oplogSize=2048
配置文件常用选项:
--dbpath 指定数据库的目录。
--port 指定数据库端口,模式是27017。
--bind_ip 绑定IP。
--derectoryperdb为每个db创建一个独立子目录。
--logpath 指定日志存放目录。
--logappend 指定日志生成方式(追加/覆盖)。
--pidfilepath 指定进程文件路径,如果不指定,将不产生进程文件。
--keyFile 集群模式的关键标识
--journal 启用日志
--nssize 指定.ns文件的大小,单位MB,默认是16M,最大2GB。
--maxConns 最大的并发连接数。
--notablescan 不允许进行表扫描
--noprealloc 关闭数据文件的预分配功能
--fork 以后台Daemon形式运行服务
- 添加环境变量
export PATH=<mongodb-install-directory>/bin:$PATH
- 启动
mongod -f /usr/local/mongodb/etc/mongodb.conf
启动后可以通过mongo命令连接到数据库
数据库基本操作
- 查看数据库
show dbs
> show dbs
admin 0.000GB
local 0.000GB
test 0.000GB
- 切换和创建数据库
use db (如果存在则切换如果不存在则创建)
> use admin
switched to db admin
- 删除数据库
db.dropDatabase()
> use test
switched to db test
> db.dropDatabase()
{ "dropped" : "test", "ok" : 1 }
> show dbs
admin 0.000GB
local 0.000GB
- 创建集合(相当于关系型数据库中的表)写入文档
db.collectionname.insert({json内容})
> use test
switched to db imooc
> db.test_collection.insert({name:"jihaitao"})
WriteResult({ "nInserted" : 1 })
- 查询集合
show collections
> show collections
test_collection
- 查询集合内容
> db.test_collection.find()
{ "_id" : ObjectId("5a17bda0cd1d754638319399"), "name" : "jihaitao" }
> db.test_collections.find({"name":"jihaitao"})
{ "_id" : ObjectId("5a17bda0cd1d754638319399"), "name" : "jihaitao" }
_id是mongoDB自己生成的字段全局唯一字段,_id可以在插入数据时自己指定,但是不能跟已有的_id重复。
> db.test_collections.insert({name:"sky",_id:12345})
WriteResult({ "nInserted" : 1 })
> db.test_collections.find()
{ "_id" : ObjectId("5a17be74cd1d75463831939a"), "name" : "jihaitao" }
{ "_id" : 12345, "name" : "sky" }
- 一些查询选项
先插入多个字段
> for(i=3;i<50;i++)db.test_collections.insert({x:i})
WriteResult({ "nInserted" : 1 })
> db.test_collections.find()
{ "_id" : ObjectId("5a17c17960660ca23324fb88"), "name" : "jihaitao" }
{ "_id" : ObjectId("5a17c31960660ca23324fb89"), "x" : 3 }
{ "_id" : ObjectId("5a17c31960660ca23324fb8a"), "x" : 4 }
{ "_id" : ObjectId("5a17c31960660ca23324fb8b"), "x" : 5 }
{ "_id" : ObjectId("5a17c31960660ca23324fb8c"), "x" : 6 }
{ "_id" : ObjectId("5a17c31960660ca23324fb8d"), "x" : 7 }
{ "_id" : ObjectId("5a17c31960660ca23324fb8e"), "x" : 8 }
{ "_id" : ObjectId("5a17c31960660ca23324fb8f"), "x" : 9 }
{ "_id" : ObjectId("5a17c31960660ca23324fb90"), "x" : 10 }
{ "_id" : ObjectId("5a17c31960660ca23324fb91"), "x" : 11 }
{ "_id" : ObjectId("5a17c31960660ca23324fb92"), "x" : 12 }
{ "_id" : ObjectId("5a17c31960660ca23324fb93"), "x" : 13 }
{ "_id" : ObjectId("5a17c31960660ca23324fb94"), "x" : 14 }
{ "_id" : ObjectId("5a17c31960660ca23324fb95"), "x" : 15 }
{ "_id" : ObjectId("5a17c31960660ca23324fb96"), "x" : 16 }
{ "_id" : ObjectId("5a17c31960660ca23324fb97"), "x" : 17 }
{ "_id" : ObjectId("5a17c31960660ca23324fb98"), "x" : 18 }
{ "_id" : ObjectId("5a17c31960660ca23324fb99"), "x" : 19 }
{ "_id" : ObjectId("5a17c31960660ca23324fb9a"), "x" : 20 }
{ "_id" : ObjectId("5a17c31960660ca23324fb9b"), "x" : 21 }
Type "it" for more
查询条数
> db.test_collections.find().count()
48
其他选项
> db.test_collections.find().skip(3).limit(3).sort({x:1})
{ "_id" : ObjectId("5a17c31960660ca23324fb8b"), "x" : 5 }
{ "_id" : ObjectId("5a17c31960660ca23324fb8c"), "x" : 6 }
{ "_id" : ObjectId("5a17c31960660ca23324fb8d"), "x" : 7 }
- 数据更新
db.test_collections.update({匹配的数据},{替换的数据})
> db.test_collections.find({x:10})
{ "_id" : ObjectId("5a17c31960660ca23324fb90"), "x" : 10 }
> db.test_collections.update({x:10},{x:999})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test_collections.find({x:10})
> db.test_collections.find({x:999})
{ "_id" : ObjectId("5a17c31960660ca23324fb90"), "x" : 999 }
部分更新
> db.test_collections.insert({x:100,y:100,z:100})
WriteResult({ "nInserted" : 1 })
> db.test_collections.update({x:100},{y:99})
#上面这个情况会把 {x:100,y:100,z:100} 整体替换成{y:99} 而不是只替换y。正确的方法是:
> db.test_collections.update({x:100},{$set:{y:99}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test_collections.find({x:100})
{ "_id" : ObjectId("5a17c86160660ca23324fbb8"), "x" : 100, "y" : 99, "z" : 100 }
更新不存在的数据
> db.test_collections.update({y:100},{y:999})
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
> db.test_collections.find({y:100})
> db.test_collections.find({y:999})
可以看到失败了
> db.test_collections.update({y:100},{y:999},true)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5a17caec37dea190b750a188")
})
> db.test_collections.find({y:999})
{ "_id" : ObjectId("5a17caec37dea190b750a188"), "y" : 999 }
update默认更新匹配到的第一条数据,如何更新多条数据?
#我们先插入3条c:1的数据
> db.test_collections.insert({c:1})
WriteResult({ "nInserted" : 1 })
> db.test_collections.insert({c:1})
WriteResult({ "nInserted" : 1 })
> db.test_collections.insert({c:1})
WriteResult({ "nInserted" : 1 })
#查询一下共3条
> db.test_collections.find({c:1})
{ "_id" : ObjectId("5a17cc7060660ca23324fbb9"), "c" : 1 }
{ "_id" : ObjectId("5a17cc7160660ca23324fbba"), "c" : 1 }
{ "_id" : ObjectId("5a17cc7260660ca23324fbbb"), "c" : 1 }
#update一下看看,可以看到更新了一条还有2条c:1
> db.test_collections.update({c:1},{c:2})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test_collections.find({c:1})
{ "_id" : ObjectId("5a17cc7160660ca23324fbba"), "c" : 1 }
{ "_id" : ObjectId("5a17cc7260660ca23324fbbb"), "c" : 1 }
> db.test_collections.find({c:2})
{ "_id" : ObjectId("5a17cc7060660ca23324fbb9"), "c" : 2 }
#update第四个参数muti,默认是false。当它为true的时候,update方法会首先查找与第一个参数匹配的记录。因此设成true即可。
> db.test_collections.update({c:1},{$set{c:2}},false,true)
2017-11-23T23:46:50.494-0800 E QUERY [thread1] SyntaxError: missing : after property id @(shell):1:38
> db.test_collections.update({c:1},{$set:{c:2}},false,true)
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
> db.test_collections.find({c:1})
> db.test_collections.find({c:2})
{ "_id" : ObjectId("5a17cc7060660ca23324fbb9"), "c" : 2 }
{ "_id" : ObjectId("5a17cc7160660ca23324fbba"), "c" : 2 }
{ "_id" : ObjectId("5a17cc7260660ca23324fbbb"), "c" : 2 }
- 数据删除
删除字段
db.test_collections.remove({json})
> db.test_collections.find({c:2})
{ "_id" : ObjectId("5a17cc7060660ca23324fbb9"), "c" : 2 }
{ "_id" : ObjectId("5a17cc7160660ca23324fbba"), "c" : 2 }
{ "_id" : ObjectId("5a17cc7260660ca23324fbbb"), "c" : 2 }
> db.test_collections.remove({c:2})
WriteResult({ "nRemoved" : 3 })
> db.test_collections.find({c:2})
删除集合
> db.test_collections.drop()
true
> show collections
>
索引
mangodb中如果数据很多,根据指定条件查询会不返回值,这时候需要将指定值设置为索引。添加索引会提高查询效率。
- 查询索引
> db.test_collections.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test_collections"
}
]
- 添加x字段为集合的索引(如数据量较大需要消耗一定时间)
> db.test_collections.ensureIndex({x:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
-
索引类型
备份与恢复
- 备份
mongodump -h dbhost -d dbname -o dbdirectory
-h:
MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
-d:
需要备份的数据库实例,例如:test
-o:
备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。
[root@vm172-26-0-15 mongodb]# mongodump -h 127.0.0.1 -d test -o /tmp/
2017-11-28T15:22:25.985+0800 writing test.test_collections to
2017-11-28T15:22:25.987+0800 done dumping test.test_collections (47 documents)
[root@vm172-26-0-15 mongodb]# cd /tmp/
[root@vm172-26-0-15 tmp]# ls
index.html mongodb-27017.sock Python-3.6.3 test
- 恢复
mongorestore -h <hostname><:port> -d dbname <path>
--host <:port>, -h <:port>:
MongoDB所在服务器地址,默认为: localhost:27017
--db , -d :
需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
--drop:
恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!
<path>:
mongorestore 最后的一个参数,设置备份数据所在位置,例如:c:\data\dump\test。
你不能同时指定 <path> 和 --dir 选项,--dir也可以设置备份目录。
--dir:
指定备份的目录
你不能同时指定 <path> 和 --dir 选项。
#先删除test数据库
> use test
switched to db test
> db.dropDatabase()
{ "dropped" : "test", "ok" : 1 }
#然后退出mongo
[root@vm172-26-0-15 test]# mongorestore -h 127.0.0.1:27017 -dir /tmp/test
2017-11-28T16:18:05.157+0800 the --db and --collection args should only be used when restoring from a BSON file. Other uses are deprecated and will not exist in the future; use --nsInclude instead
2017-11-28T16:18:05.158+0800 building a list of collections to restore from /tmp/test dir
2017-11-28T16:18:05.158+0800 reading metadata for ir.test_collections from /tmp/test/test_collections.metadata.json
2017-11-28T16:18:05.164+0800 restoring ir.test_collections from /tmp/test/test_collections.bson
2017-11-28T16:18:05.166+0800 restoring indexes for collection ir.test_collections from metadata
2017-11-28T16:18:05.171+0800 finished restoring ir.test_collections (47 documents)
2017-11-28T16:18:05.171+0800 done
#再看一下数据库是否恢复
> show dbs
admin 0.000GB
local 0.000GB
test 0.000GB
在程序中中使用mongoDB
- eg:python
from pymongo import MongoClient
conn = MongoClient('192.168.0.113', 27017)
db = conn.mydb #连接mydb数据库,没有则自动创建
my_set = db.test_set #使用test_set集合,没有则自动创建
#插入数据
my_set.insert({"name":"zhangsan","age":18})
#或
my_set.save({"name":"zhangsan","age":18})
#查询数据
for i in my_set.find({"name":"zhangsan"}):
print(i)