游标操作
1、游标是什么?
通俗的说游标不是查询结果,而是查询的返回资源或者接口,就像python中的生成器,通过这个生成器,可以一次一次的获取每一个资源。
2、游标的声明:
var curor_name = db.bar.find()
3、游标的操作:
curor.hasNext()//判断游标是否已经取到尽头
curor.next()//取出游标的下一个单元
例如:
var mycusor = db.bar.find().limit(5)
print(mycusor.next())//会显示是一个bson格式的数据
printjson(mycusor.next())
我们可以写一个while循环来打印游标结果:
while(mycusor.hasNext()){
printjson(mycusor.next())
}
游标还有一个toArray()方法,方便我们可以看到所有行
print(mycusor.toArray())//看到所有行
print(mycusor.toArray()[2])//看到第二行
注意不要使用toArray(),原因是会把所有的行立即以对象的形式放在内存中,可以再取出少数几行时,使用此功能。
4、cursor.forEach(回调函数)
var gettile = function(obj){print(obj.goods_name)}
var cursor = db.goods.find()
cursor.forEach(gettile)
5、游标在分页中的应用
一般的,我们假设每页N行,当前是page页,就需要跳过(page-1)*N,再取N行,在mysql中,用limit,offset,N来实现,在MongoDB中,用skip(),limit()函数来实现。
var mycusor = db.bar.find().skip(90).limit(10)//跳过90条,取10条。
查询第901页,每页10条
则是 var mytcursor = db.bar.find().skip(9000).limit(10);
索引
- 索引提高查询速度,降低写入速度,权衡常用的查询字段,不必在太多列上建索引
- 在mongodb中,索引可以按字段升序/降序来创建,便于排序
- 默认是用btree来组织索引文件,2.4版本以后,也允许建立hash索引
btree
hash索引
hash索引缺点:
Hash检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到数据节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
但是任何事物都有两面性,他的特殊性也带来了很多弊端和限制。
hash索引缺点:
(1)Hash 索引仅仅能满足"=","IN"和"<=>"查询,不能使用范围查询。
(2)Hash 索引无法被用来避免数据的排序操作。
由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;
(3)Hash 索引不能利用部分索引键查询。
对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。
(4)Hash 索引在任何时候都不能避免表扫描。
Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。
(5)Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。
常用命令
(1)查看当前索引状态:
db.collectionName.getIndexes()
(2)创建普通单列索引:1为正序,-1为逆序
db.collectionName.ensureIndex({field:-1})
(3)删除单个索引:1为正序,-1为逆序
db.collectionName.dropIndex({field:-1})
(4)删除所有索引:
db.collectionName.dropIndexes()
(5)创建多列索引:多个列一起建立索引其实就是将两个列绑定到一起,来创建索引
db.collectionName.ensureIndex({field1:1,field2:-1})
(6)子文档索引:
子文档查询:
1.插入两条带子文档的数据
db.shop. insert({name: 'N0kia' , SPC: {weight: 120 , area: ' taiwan ' } } ) ;
db.shop. insert({name: 'sanxing ' , SPC :{weight: 100 , area: 'hanguo'} } ) ;
2.查询出产地在台湾的手机
db.shop.find({'spc.area':'taiwan'})
给子文档加索引:
db.shop.ensureIndex({'spc.area':1})//子文档就点就可以了
(7) 唯一索引:{unique:true},唯一索引的列不能重复插入
db.collection.ensureIndex({field:1/-1},{unique:true})
(8)创建稀疏索引:{sparse:true}
稀疏索引的特点:如果针对field列做索引,针对不含field的列的文档,将不建立索引,与之相对,普通索引,会把该文档的field列的值认为null,并建立索引。
db.collection.ensureIndex({field:1/-1},{sparse:true})
(9)hash索引:
db.collection.ensureIndex({field:'hashed'})
数据导入和导出
1.通用选项
导入/导出可以操作本地的MongoDB服务器,也可以是远程的
通用选项如下
-h host 主机
--port port 端口
-u username 用户名
-p passwd 密码
2.mongoexport 导出json格式的文件
-d 库名
-c 表名
-f field1,field2.... 列名
-q 查询条件
-o 导出的文件名
--type csv 导出csv格式(便于和传统数据库交换数据)
例1:导出全部数据
mongoexport -d shop -c goods -o goods.json
例2:只导出goods_id,goods_name列
mongoexport -d shop -c goods -f goods_id,goods_name -o goods.json
例3:只导出价格低于1000的数据
mongoexport -d test -c goods -f goods_id,goods_name,shop_price -q ‘{shop_price:{$lt:200}}’ -o goods.json
例4:导出成csv形式
mongoexport -d shop -c goods -o goods.csv --type csv -f goods_id,goods_name,goods_number
3.MongoDB导入
-d 待导入的数据库
-c 待导入的表
--type csv/json(默认)
--file 备份文件路径
例1:导入json
mongoimport -d shop -c goods --file ./goods.json
例2:导入csv
mongoimport -d shop -c goods --type csv -f goods_id,goods_number --file ./goods.csv
4.导出二进制bson结构数据及其索引信息
规律:
-
导出的文件放在以database命名的目录下
-
每个表导出2个文件,分别是bson结构的数据文件, json的索引信息
-
如果不声明表名, 导出所有的表
-d 库名
-c 表名
例1:导出bson格式
mongodump -d shop -c goods
5.mongorestore导入二进制文件
mongorestore -d shop -c goods --dir ./dump/shop/goods.bson
replaction复制集
一般情况下,我们通常在机器上安装了一个数据库,这是我们的数据都是存在这个数据库中的,如果有一天,因为一些不可控因素导致数据库宕机或者数据库的文件丢失,此时损失就很大了。针对于这种问题,我们希望有一个数据库集,在我们其中一个数据库进行插入的时候,其他数据库也能插入数据,这样其中一台服务器宕机了,也能够使我们的数据正常存取。
在MongoDB中,是通过replaction复制集来实现此功能的。
1.在Windows下实现复制集的方法:
创建复制集之前,把所有的mongo进程都关掉
(1)创建三个存储数据库的文件夹
(2)在logs文件夹下,创建3个日志文件,用来记录启动的三个mongodb数据库的日志信息(会自动创建)
(3)打开三个cmd窗口,分别启动三个mongodb
其中的–replSet就表示创建的数据集的名称,必须指定相同的名称才可以
mongod --dbpath C:\MongoDB\Server\3.4\data\db1 --logpath C:\MongoDB\Server\3.4\data\logs\mongo1.log --port 27017 --replSet rs
mongod --dbpath C:\MongoDB\Server\3.4\data\db2 --logpath C:\MongoDB\Server\3.4\data\logs\mongo2.log --port 27018 --replSet rs
mongod --dbpath C:\MongoDB\Server\3.4\data\db3 --logpath C:\MongoDB\Server\3.4\data\logs\mongo3.log --port 27019 --replSet rs
(4) 配置
_id:0 为主库
var rsconf = {
_id:'rs',
members:[
{_id:0,host:'127.0.0.1:27017'},
{_id:1,host:'127.0.0.1:27018'},
{_id:2,host:'127.0.0.1:27019'}
]
}
这时候我们可以打印rsconf来看一下
printjson(rsconf)
接下来需要将配置初始化
rs.initiate(rsconf)
show dbs
现在我们看到,现在登录客户端已经不是哪台机器,而是rs复制集
(5)给从库授权,使可以读取数据
re.slaveOk()
2.删除复制集
rs.remove('127.0.0.1:27019')
删除节点后,如果想再添加,必须重新配置才可以。
var rsconf = {
_id:'rs',
members:[
{_id:0,host:'127.0.0.1:27017'},
{_id:1,host:'127.0.0.1:27018'},
{_id:2,host:'127.0.0.1:27019'}
]
}
在输入:rs.reconfig(rsconf)
3.查看复制集状态
rs.status()