关系型数据库中的表都是存储一些结构化的数据,每条记录的字段的组成都一样,即使不是每条记录都需要所有的字段,但数据库会为每条数据分配所有的字段。而非关系型数据库以键值对(key-value)存储,它的结构不固定,每一条记录可以有不一样的键,每条记录可以根据需要增加一些自己的键值对,这样就不会局限于固定的结构,可以减少一些时间和空间的开销。
常见的非关系型数据库:
CouchDB
Redis
MongoDB
Neo4j
HBase
BigTable
NoSQL优缺点:
优点:扩展简单\快速读写\成本低廉\数据模型灵活
缺点:不提供对sql的支持\支持的特性不够丰富\现有产品不够成熟
MongoDB是C++语言编写的NoSQL。高性能、易部署、易使用,存储数据十分方便.
主要特性有:
面向集合存储,易于存储对象类型的数据
模式自由
支持动态查询
支持完全索引,包含内部对象
支持复制和故障恢复
使用高效的二进制数据存储,包括大型对象
文件存储格式为BSON(一种JSON的扩展)
MongoDB的安装非常简单,只需要将下载的MongoDB的压缩文件解压到任意目录,并将其中的bin目录加入到系统的path环境变量中即可
在启动MongoDB之前,要手动创建一个存放MongoDB数据文件的目录,如D:\mongo_data
1、启动命令:mongod --dbpath=d:\mongo_data
2、连接到mongodb服务器用的是mongo命令
mongo 默认连接到本地的名称为test的数据库
mongo ip:port 链接到远程数据库(mongo 192.168.1.11:27017)
3、创建数据库: use 数据库名
4、删除当前数据库:db.dropDatabase()
5、查看所有数据库:show dbs
6、查看当前所在数据库:db
7、查看当前数据库中所有的集合:show collections或show tables
8、显式创建集合:db.createCollection("集合名称")
隐式创建集合:db.集合成名.insert({}) 指创建集合的同时向集合中插入数据
9、向集合中添加文档:db.集合名称.insert({})
10、删除集合中的文档:db.集合名称.remove({产出条件});
例如:db.c1.remove({name:"user1"})
11、查询集合中的文档,可以使用命令 db.集合名称.find({条件}),或者使用 db.集合名称.findOne() 查询第一个文档
db.c1.find({},{age:0}) 返回除了age字段外的所有字段
db.c1.find({tags:"finn"},{comment:0}) 返回tags=finn除了comment的所有列
db.c1.find({userid:16},{name:1}) 返回userid=16的name列
_id字段始终都会被返回,哪怕没有明确指定
/ /大于: field > value
db.collection.find({field:{$gt:value}});
//小于: field < value
db.collection.find({field:{$lt:value}});
//大于等于: field >= value
db.collection.find({field:{$gte:value}});
//小于等于: field <= value
db.collection.find({field:{$lte:value}});
//不等于: field != value
db.collection.find({field:{$ne:value}});
统计(count) 、排序(sort)、分页(skip,limit)
db.customer.count();
db.customer.find().count();
db.customer.find({age:{$lt:5}}).count();
db.customer.find().sort({age:1}); 降序-1
db.customer.find().skip(2).limit(3);
db.customer.find().sort({age:-1}).skip(2).limit(3);
db.customer.find().sort({age:-1}).skip(2).limit(3).count();
db.customer.find().sort({age:-1}).skip(2).limit(3).count(0);
db.customer.find().sort({age:-1}).skip(2).limit(3).count(1);
$all主要用来查询数组中的包含关系,查询条件中只要有一个不包含就不返回
db.c1.find({p:{$all:[1,2]}})
$in,类似于关系型数据库中的IN
db.c1.find({p:{$in:[2,3,5]}})
$nin,与$in相反
db.c1.find({p:{$nin:[2,3,4]}})
$or,相当于关系型数据库中的OR,表示或者的关系
db.customer.find({$or:[{name:”user2”},{age:3}]})
$nor,表示根据条件过滤掉某些数据
db.customer.find({$nor:[{name:”user2”},{age:3}]}) 查询name不是user2,age不是3的文档
$exists,用于查询集合中存在某个键的文档或不存在某个键的文档 $exists:1表示真,指存在 ;$exists:0表示假,指不存在
db.c1.find({name:{$exists:1}})
游标:var x=db.c1.find();x.hasNext();x.next();
12、更新文档 db.集合名字.update(criteria,objNew,upsert,multi);
criteria:用于设置查询条件的对象
objNew:用于设置更新内容的对象
upsert:如果记录已经存在,更新它,否则新增一个记录,取值为0或1
multi:如果有多个符合条件的记录,是否全部更新,取值为0或1
注意:默认情况下,只会更新第一个符合条件的记录
一般情况下后两个参数分别为0,1 ,即:
db.collection.update(criteria,objNew,0,1)
$set 用来指定一个键的值,如果这个键不存在,则创建它
db.c1.update({name:"user1"},{$set:{addr:"sh"}},0,1)
$inc 将集合中name为user1的age加1,其它键不变, $inc表示使某个键值加减指定的数值
db.c1.update({name:"user1"},{$inc:{age:1}},0,1)
$unset 用来删除某个键
db.c1.update({name:"user1"},{$unset:{addr:1}},0,1)
13、索引:索引就是用来加速查询的。数据库索引与书籍的索引类似:有了索引就不需要翻遍整本书,数据库则可以直接在索引中查找,使得查找速度能提高几个数量级。在索引中找到条目以后,就可以直接跳转到目标文档的位置。
创建普通索引,使用命令 db.collection.ensureIndex({key:1})
查看关于索引的相关信息,使用命令 db.collection.stats()
查看查询使用索引的情况,使用命令 db.collection.find({key:value}).explain()
删除索引,使用命令 db.collection.dropIndex({key:1})
删除集合,也会将集合中的索引全部删除
创建唯一索引,使用命令 db.collection.ensureIndex({key:1},{unique:true})
14、固定集合:固定集合指的是事先创建而且大小固定的集合 。
固定集合特性:固定集合很像环形队列,如果空间不足,最早的文档就会被删除,为新的文档腾出空间。一般来说,固定集合适用于任何想要自动淘汰过期属性的场景,没有太多的操作限制
db.createCollection(“collectionName”,{capped:true,size:100000,max:100});
size指定集合大小,单位为KB,max指定文档的数量
当指定文档数量上限时,必须同时指定大小。淘汰机制只有在容量还没有满时才会依据文档数量来工作。要是容量满了,淘汰机制会依据容量来工作。
15、备份(mongodump)和恢复(mongorestore)
>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目录,这个目录里面存放该数据库实例的备份数据。
>mongorestore -h dbhost -d dbname -directoryperdb dbdirectory
-h:MongoDB所在服务器地址
-d:需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
-directoryperdb:备份数据所在位置,例如:c:\data\dump\test
16、导入(mongoimport)和导出(mongoexport)
mongoexport -h dbhost -d dbname -c collectionName -o output
-h 数据库地址
-d 指明使用的库
-c 指明要导出的集合
-o 指明要导出的文件名
mongoimport -h dbhost -d dbname -c collectionname 文件的地址...
-h 数据库地址
-d 指明使用的库
-c 指明要导入的集合
17、安全和认每个MongoDB实例中的数据库都可以有许多用户。如果开启了安全性检查,则只有数据库认证用户才能执行读或者写操作。
在认证的上下文中,MongoDB会将普通的数据作为admin数据库处理。admin数据库中的用户被视为超级用户(即管理员)。
在认证之后,管理员可以读写所有数据库,执行特定的管理命令,如listDatabases和shutdown。
在开启安全检查之前,一定要至少有一个管理员账号证
在admin数据库中创建管理员账号:
use admin;
db.addUser(“root”,”root”);
在test数据库中创建普通账号:
use test;
db.addUser(“zhangsan”,”123”);
db.addUser(“lisi”,”123”,true);
注意:用户zhangsan,密码为123,对test数据库拥有读写权限
用户lisi,密码为123,对test数据库拥有只读权限
重新启动数据库服务,并开启安全检查:
mongod --dbpath d:\mongo_data --auth
18、主从复制:主从复制是MongoDB最常用的复制方式。这种方式非常灵活,可用于备份、故障恢复、读扩展等。
最基本的设置方式就是建立一个主节点和一个或者多个从节点,每个从节点要知道主节点的地址。运行mongod --master就启动了主服务器。运行mongod --slave --source master_address 则启动了从服务器,其中master_address就是上面主节点的地址。
注意:主节点和从节点要指定不同的端口。
启动主节点:mongod --dbpath d:\master --port 10000 --master
启动从节点:mongod --dbpath d:\slave --port 10001 --slave --source localhost:10000
启动成功后就可以连接主节点进行操作了,而这些操作会同步到从节点。
19、副本集:副本集就是有自动故障恢复功能的主从集群。
主从集群和副本集最大的区别就是副本集没有固定的“主节点”;整个集群会选出一个“主节点”,当其挂掉后,又在剩下的从节点中选中其他节点为“主节点”,副本集总有一个活跃点(primary)和一个或多个备份节点(secondary)。
启动节点1:
mongod --dbpath D:\mongodb\dbs\node1 --logpath D:\mongodb\logs\node1\logs.txt --logappend --port 10001 --replSet itcast/localhost:10002 --master
启动节点2:
mongod --dbpath D:\mongodb\dbs\node2 --logpath D:\mongodb\logs\node2\logs.txt --logappend --port 10002 --replSet itcast/localhost:10001
启动节点3:
mongod --dbpath D:\mongodb\dbs\node3 --logpath D:\mongodb\logs\node3\logs.txt --logappend --port 10003 --replSet itcast/localhost:10001,localhost:10002
初始化节点(只能初始化一次):随便登录一个节点,以10001为例
mongo localhost:10001/admin
db.runCommand({"replSetInitiate":{ "_id":“itcast", "members":[ {"_id":1, "host":"localhost:10001","priority":3 }, { "_id":2, "host":"localhost:10002", "priority":2 }, { "_id":3, "host":"localhost:10003", "priority":1 } ]}});
查询当前主库,登录10002
mongo localhost:10002
db.$cmd.findOne ( {ismaster: 1 } );
20、分片:设置分片时,需要从集合里面选一个键,用该键的值作为数据拆分的依据。这个键称为片键(shard key)。
{name:"zhangsan",age:1}
用个例子来说明这个过程:假设有个文档集合表示的是人员。如果选择名字("name")作为片键,第一片可能会存放名字以A~F开头的文档,第二片存的G~P的名字,第三片存的Q~Z的名字。随着添加或者删除片,MongoDB会重新平衡数据,使每片的流量都比较均衡,数据量也在合理范围内。