mongodb_2
叶落西南 人气:1
#### 一、游标
在mongodb中,底层使用js引擎进行各种操作,所以我们在命令行窗口,可直接执行js代码。
```
#使用for循环,插入1000条数据。
> for (var i=0;i<1000;i++){ db.test.insertOne({_id:i,name:"erha"+i})}
{ "acknowledged" : true, "insertedId" : 999 }
> db.test.find()
#查询结果如下
{ "_id" : 0, "name" : "erha0" }
{ "_id" : 1, "name" : "erha1" }
{ "_id" : 2, "name" : "erha2" }
{ "_id" : 3, "name" : "erha3" }
{ "_id" : 4, "name" : "erha4" }
{ "_id" : 5, "name" : "erha5" }
{ "_id" : 6, "name" : "erha6" }
{ "_id" : 7, "name" : "erha7" }
{ "_id" : 8, "name" : "erha8" }
{ "_id" : 9, "name" : "erha9" }
```
我们使用find()方法查询时,他会将所有的数据都查询出来给我们,但是当数据量特别大的时候,这种操作并不是很好。我们希望就像python中生成器那样,我们需要数据,调用某些方法,就给我们返回数据。其实在MongoDB中也有类似生成器对象的东西,在mongo中叫做游标。
##### 1.1、游标操作
我们将查询的结果,赋值给一个变量,则该变量就是一个游标。
```
> var con= db.test.find()
> con.next() #取出该游标下一个元素。
{ "_id" : 0, "name" : "erha0" }
> con.hasNext() #判断该游标是否有下一个元素。
true
#还可以进行循环打印
> while(mycusor.hasNext()){
... printjson(mycusor.next())
... }
{ "_id" : 0, "name" : "erha0" }
{ "_id" : 1, "name" : "erha1" }
{ "_id" : 2, "name" : "erha2" }
{ "_id" : 3, "name" : "erha3" }
{ "_id" : 4, "name" : "erha4" }
{ "_id" : 5, "name" : "erha5" }
{ "_id" : 6, "name" : "erha6" }
{ "_id" : 7, "name" : "erha7" }
{ "_id" : 8, "name" : "erha8" }
{ "_id" : 9, "name" : "erha9" }
#可将所有元素取出到一个数组内
> var mycusor = db.test.find().limit(2)
> mycusor.toArray()
[
{
"_id" : 0,
"name" : "erha0"
},
{
"_id" : 1,
"name" : "erha1"
}
]
```
##### 1.2、forEach(回调函数)
```
> var mycusor = db.test.find().limit(10)
> var get_name=function(obj){ #定义一个函数,打印每个元素的name属性。
... print(obj.name)}
> mycusor.forEach(get_name)
erha0
erha1
erha2
erha3
erha4
erha5
erha6
erha7
erha8
erha9
```
##### 1.3、游标在分页中的使用
```
#每页5个。
> var mycusor = db.test.find().skip(0).limit(5)
> var mycusor = db.test.find().skip(5).limit(5)
#总结如下
m:页码
n:每页元素
> var mycusor = db.test.find().skip((m-1)*n).limit(n)
> mycusor.toArray()
```
#### 二、索引
- 索引提高查询速度,降低写入速度,一般在常用的查询字段建立索引。
- 在mongodb中,索引可以按字段升序/降序来创建,便于排序。
- 默认是用btree来组织索引文件,2.4版本以后,也允许建立hash索引。
##### 2.1、常用命令
```
(1)查看当前索引状态:db.collection.getIndexes()
> db.test.getIndexes()
[
{
"v" : 2, #版本
"key" : {
"_id" : 1 #排序方式
},
"name" : "_id_", #索引名
"ns" : "test.test" #数据库.表
}
]
(2)创建普通单列索引:db.collection.ensureIndex({field:1/-1})//1为正序,-1为逆序
> db.test.ensureIndex({name:-1})
> db.test.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test"
},
{
"v" : 2,
"key" : {
"name" : -1
},
"name" : "name_-1",
"ns" : "test.test"
}
]
(3)删除单个索引:db.collection.dropIndex({field:1/-1})
> db.test.dropIndex({name:-1}) #这里的-1,跟设置时的保持一致。
{ "nIndexesWas" : 2, "ok" : 1 }
> db.test.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test"
}
]
(4)删除所有索引:db.collection.dropIndexes()
# _id所在的列的索引不能删除。
(5)创建多列索引:db.collection.ensureIndex({field1:1/-1,field2:1/-1})
> db.test.ensureIndex({_id:1,name:1})
> db.test.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test"
},
{
"v" : 2,
"key" : {
"_id" : 1,
"name" : 1
},
"name" : "_id_1_name_1",
"ns" : "test.test"
}
]
(6)创建多列索引:db.collection.dropIndex({field1:1/-1,field2:1/-1})
> db.test.dropIndex({"_id" : 1,"name" : 1})
> db.test.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test"
}
]
(7)创建hash索引
> db.test.ensureIndex({name:'hashed'})
> db.test.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test"
},
{
"v" : 2,
"key" : {
"name" : "hashed"
},
"name" : "name_hashed",
"ns" : "test.test"
}
]
(8)为子文档创建索引
#插入数据
db.goods. insert({name: 'N0kia' , SPC:{weight: 120 , area: ' taiwan ' } } )
db.goods. insert({name: 'sanxing ' , SPC:{weight: 100 , area: 'hanguo'} } )
#查询产地为韩国的产品名
> db.goods.find({'SPC.area':'hanguo'},{name:1,_id:0})
{ "name" : "sanxing " }
#创建索引
> db.goods.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.goods"
}
]
> db.goods.ensureIndex({'SPC.weight':1})
> db.goods.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.goods"
},
{
"v" : 2,
"key" : {
"SPC.weight" : 1
},
"name" : "SPC.weight_1",
"ns" : "test.goods"
}
]
(9)、唯一索引,设置了唯一索引的列,元素不能重复
> db.goods.ensureIndex({"SPC.weight":1},{unique:1})
#插入weight相同的数据
> db.goods. insert({name: 'N0kia' , SPC:{weight: 120 , area: ' taiwan ' } } )
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.goods index: SPC.weight_1 dup key: { SPC.weight: 120.0 }"
}
})
```
#### 三、mongodb数据库的导出与导入
##### 3.1、通用选项
```
--host host 主机
--port port 端口
-u username 用户名
-p passwd 密码
```
##### 3.2、导出
```
-d 库名
-c 表名
-f field1,field2...列名
-q 查询条件
-o 导出的文件名。
--type csv 导出csv格式(便于和传统数据库交换数据),需要指定列名。
--skip 跳过多少个
--limit 指定导出多少个
-- sort: 导出时,可指定字段排序
```
###### 示例1、导出json
```
mongoexport -d shop -c goods -o goods.json
```
###### 示例2、导出指定字段为csv文件
```
mongoexport -d shop -c goods -f "goods_id","goods_name","shop_price" --type csv -o goods.csv
```
![](https://img2020.cnblogs.com/blog/1870442/202004/1870442-20200402001339780-1191657002.png)
###### 示例3、导出指定数量,并且按照价格从高到低排序
```
mongoexport -d shop -c goods --limit 5 --sort {shop_price:-1} --f "goods_id","goods_name","shop_price" --type csv -o goods.csv
```
![](https://img2020.cnblogs.com/blog/1870442/202004/1870442-20200402001349059-1324334655.png)
##### 3.3、导入
```
-d 待导入的数据库
-c 待导入的表(不存在会自己创建)
--file 备份文件路径
```
###### 示例1、导入json
```
mongoimport -d douban -c top250 --file .https://img.qb5200.com/download-x/doubantop250.json
```
###### 示例2、导入csv
```
mongoimport -d test -c shop --type csv -f "goods_id","goods_name","shop_price" ./goods.csv
> use test
> db.shop.find()
{ "_id" : ObjectId("5e844e4d05ffa52ba53b45b4"), "goods_id" : 3, "goods_name" : "诺基亚原装5800耳机", "shop_price" : 68 }
{ "_id" : ObjectId("5e844e4d05ffa52ba53b45b5"), "goods_id" : 5, "goods_name" : "索爱原装M2卡读卡器", "shop_price" : 20 }
...
```
##### 3.4、导出为二进制
```
-d 库名
-c 表名
#默认导出到执行命令位置dump目录下
#导出的文件放在以database命名的目录下
#每个表导出2个文件,分别是bson结构的数据文件, json的索引信息
#如果不声明表名, 导出所有的表。
```
###### 示例1、导出一个数据库下的所有表。
```
mongodump -d test
```
###### 示例2、导出指定表
```
mongodump -d shop -c goods
```
![](https://img2020.cnblogs.com/blog/1870442/202004/1870442-20200402001406136-2059034960.png)
##### 3.5、导入二进制文件
```
mongorestore -d shop1 -c goods --dir .https://img.qb5200.com/download-x/dump/shop/goods.bson
> use shop1
switched to db shop1
> show tables
goods
```
#### 四、mongo复制集,类似于 redis( 主从+哨兵),以下操作都在windows上。
##### 4.1、目录准备
```
#创建数据库目录
C:\Users\28295\Desktop>md data1
C:\Users\28295\Desktop>md data2
C:\Users\28295\Desktop>md data3
#创建日志目录,及日志文件
C:\Users\28295\Desktop>md log1
C:\Users\28295\Desktop>md log2
C:\Users\28295\Desktop>md log3
C:\Users\28295\Desktop>echo >>log3\\log.log
C:\Users\28295\Desktop>echo >>log2\\log.log
C:\Users\28295\Desktop>echo >>log1\\log.log
```
##### 4.2、启动服务
```
#关闭mongodb服务(没有配置服务自启,请忽略。),启动三个服务端。
PS C:\Users\28295\Desktop\spider> net stop MongoDB #注意要用管理员权限打开命令窗口。
MongoDB 服务正在停止.
MongoDB 服务已成功停止。
#--replSet 代表复制集的名称,必须要一致。
mongod --dbpath C:\Users\28295\Desktop\data1 --logpath C:\Users\28295\Desktop\log1\log.log --port 27017 --replSet db
mongod --dbpath C:\Users\28295\Desktop\data2 --logpath C:\Users\28295\Desktop\log2\log.log --port 27018 --replSet db
mongod --dbpath C:\Users\28295\Desktop\data3 --logpath C:\Users\28295\Desktop\log3\log.log --port 27019 --replSet db
```
![](https://img2020.cnblogs.com/blog/1870442/202004/1870442-20200402001428845-1958363173.png)
##### 4.3、用客户端连接其中一台服务器,进行配置。
```
var rsconf = {
_id:'db',
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.initiate(rsconf) #初始化,主服务端随机分配。
```
初始化完成后,主服务端会变成如下样子(27018).
![](https://img2020.cnblogs.com/blog/1870442/202004/1870442-20200402001441624-1807837769.png)
从服务端下(27017,127019)
![](https://img2020.cnblogs.com/blog/1870442/202004/1870442-20200402001449374-1904175798.png)
主服务端插入数据后,从服务端必须输入rs.slaveOk()之后才能被允许查看数据,不然会报错。
```
db:PRIMARY> db.goods.insert({name:'erha',age:12})
WriteResult({ "nInserted" : 1 })
```
![](https://img2020.cnblogs.com/blog/1870442/202004/1870442-20200402001501870-638064336.png)
假如主服务器死亡(27018),则在剩下的mongodb服务器中选出一台作为主服务器。
```
rs.status() #该命令可以查看具体的复制集信息
```
![](https://img2020.cnblogs.com/blog/1870442/202004/1870442-20200402001516636-2094406893.png)
有上图可知,在我强制关闭(27018)主服务器后,(27017)此时变为了主服务器。
加载全部内容