My Little World

mongoDB使用

启动

cmd到mongoDB的bin文件夹,执行
mongod –dbpath data文件夹路径(例:D:\MongoDB\data)//运行
再打开一个cmd,同样切目录到bin文件夹下,执行
mongo //连接到数据库

命令

基础命令

use dbname //名为dbname的数据库若存在就将当前数据库切换到该数据库,若不存在,则新建该数据库并切换至该数据库
db //查看当前数据库
show dbs //查看所有数据库,新建的库,在插入数据后才会显示
db.dropDatabase() //删除当前数据库,但用db查看当前库,还是被删的这个库
db.tablename.drop() //删除数据库中名为tablename的集合
db.tablename.insert({“key”:”value”}) //创建名为objectname的表(对象),并插入数据,批量操作时可以直接在shell里面写for循环
show tables //查看该库中所有表(对象)
db.tablename.find() //在仓库中查找名为tablename的表,如果有就会将表中内容打印出来
db.tablename.find({“key”:”value”}) //在tablename表中查找具体数据,注意格式
mongodb1
db.tablename.update({查找值},{替换值}) //将查找值所在的集合替换为替换值
mongodb2
db.tablename.remove({查找值}) //删除查找值所在对象的全部数据,若为空,则将整表清空
mongodb3

条件查找

1.比较查询
将查找条件放在value部分,用{}括起来
下图查询条件为age大于”$gt”22, 大于等于”$gte”22, 小于”$lt”22, 小于等于”$lte”22, 不等于”$ne”20,等于20的查询格式
mongodb4
使用正则表达式匹配时同样将正则表达式放在value的位置,而且不用{}或者””包括,直接/开始/结束
2.逻辑查询
下图查询条件分别为且,或者$or,在氛围内$in,不在范围内$nin
mongodb5

局部修改

$inc 属性不存在就创建并赋值,如果存在,就在原来的基础上增加要修改的值
$set 仅修改

1
2
3
4
5
6
7
8
9
10
11
12
13
> db.person.find()
{ "_id" : ObjectId("58ccdcb002efa48d7589f2ae"), "name" : "jack", "age" : 20 }
{ "_id" : ObjectId("58ccdcb502efa48d7589f2af"), "name" : "joe", "age" : 25 }
{ "_id" : ObjectId("58ccdcd302efa48d7589f2b0"), "name" : "mark", "age" : 15 }
> db.person.update({"name":"jack"},{$inc:{"age":10}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.update({"name":"mark"},{$set:{"age":10}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.person.find()
{ "_id" : ObjectId("58ccdcb002efa48d7589f2ae"), "name" : "jack", "age" : 30 }
{ "_id" : ObjectId("58ccdcb502efa48d7589f2af"), "name" : "joe", "age" : 25 }
{ "_id" : ObjectId("58ccdcd302efa48d7589f2b0"), "name" : "mark", "age" : 10 }
>

特殊情况:update的第一个参数不存在,即查找值不在person中,可以如下设置,将其新增
db.person.update({“name”:”jackson”},{$inc:{“age”:10}},true)
注意:update默认仅更新匹配得到的第一个集合,如果想更新全部匹配得到的结果,
可以将第四个参数设为true

数据处理

1.计数
db.person.count() //获取person中数据条数
db.person.count({“age”:20}) // 获取person中age等于20的数据条数
2.统计
db.person.distinct(“age”) //获取person中所有age的值,重复的值只取一次
3.分组
db.person.group({
“key”:{“age”:true},//按age分组,age相同的分一组
“initial”:{“person”:[]}, //分组内容
“$reduce”:function(cur,prev){ //符合分组条件,将该条数据放入该组集合中,cur指当前处理的该条数据,prev指上次函数的累计对象,第一次为initial的值。
prev.person.push(cur.name);
},
“finalize”:function(out){//将一条数据划分到一组后执行的处理
out.count = out.person.length;
},
“condition”:{“age”:{$lt:25}}//分组条件,对什么样的数据进行分组
})
4.映射
通过map对集合进行分组,通过reduce对分组结果进行处理,理解为复杂的重组处理,最后会生成一个全新的集合

1
2
3
4
5
6
7
8
9
10
11
12
var map = function(){
emit(this.name,{count:1}); //集合按照name分组,分组内容均为{count:1}
}
var reduce = function(key,value){ //对分组结果进行处理
var result = {count:0};
for(var i = 0;i<value.length;i++){
result.count +=value[i].count;
}
return result;
}
db.person.mapReduce(map,reduce,{"out":"collection"})
db.collection.find()

5.循环处理
可以将集合赋值给一个变量然后进行循环处理,
var list = db.person.find();
list.forEach(function(x){
print(x.name):
})

6.可以多操作查询
对person集合数据按name排序然后分页
var single=db.person.find().sort({“name”,1}).skip(2).limit(2);

7.索引查询
建立索引:
db.person.ensureIndex({“name”:1}) //建立按照name进行排序的索引,1为升序,-1为降序
db.person.ensureIndex({“name”:1},{“unique”:true}) //建立唯一索引,集合中不能出现重复键值对
db.person.ensureIndex({“name”:1,”birthday”:1}) //组合索引
查询优化器做出的选择往往是最优的,因为我们做查询时,查询优化器会使用我们建立的这些索引来创建查询方案,
如果某一个先执行完则其他查询方案被close掉,这种方案会被mongodb保存起来,当然如果非要用自己指定的查询方案,这也是可以的,在mongodb中给我们提供了hint方法让我们可以暴力执行。
db.person.find({“name”:”jack”,”birthday”:”1998-3-2”}).hint({“name”:1,”birthday”:1})

删除索引:
db.person.dropIndexes(“name_1”)

主从复制

将数据库数据复制到多台服务器上,防止因为一台服务器死机而导致数据无法使用的问题出现
将安装文件复制到其他磁盘上,模拟不同的服务器
启动H盘上的mongodb,把该数据库指定为主数据库
H:\mongoDB\bin>mongod –dbpath H:\mongoDB\data –master
启动D盘上的mongodb,把该数据库指定为从属数据库
D:\mongoDB\bin>mongod –dbpath D:\mongoDB\data –port 8888 –slave –source=127.0.0.1:27017
更换端口为8888,source表示主数据库地址
2017-03-20T10:12:17.424+0800 I REPL [replslave] syncing from host:127.0.0.1:
27017
然后分别打开主shell(mongo 127.0.0.1:27017)和从shell(mongo 127.0.0.1:8888)查看所有集合
show dbs
因为从服务器上的数据库是不允许进行读写操作,所以从shell中会报错
mongodb7
解决,先执行:rs.slaveOk()
现在主shell中更改数据,在从shell中查看,看是否进行了同步
但有可能因为服务连接状态问题导致数据内容不同
mongodb8

集群

不设定特定主数据库,如果哪个数据库死机了,集群就会推选一个从属数据库作为主数据库顶上,实现自动修复的效果
1.建立集群,命名集群名为shopex,replSet让服务器知道shopex下有端口为3333的另一个数据库服务器
新打开cmd
H:\mongoDB\bin>mongod –dbpath H:\mongoDB\data –port 2222 –replSet shopex/127.0.0.1:3333
2.打开端口为3333的另一个数据库服务器
新打开cmd
D:\mongoDB\bin>mongod –dbpath D:\mongoDB\data –port 3333 –replSet shopex/127.0.0.1:2222
3.在admin集合中初始化“副本集”
新打开cmd,开启shell
H:\mongoDB\bin>mongo 127.0.0.1:2222/admin

1
2
3
4
5
6
7
8
9
10
11
12
13
> db.runCommand({"replSetInitiate":{
... "_id":"shopex",
... "members":[
... {
... "_id":1,
... "host":"127.0.0.1:2222"
... },
... {
... "_id":2,
... "host":"127.0.0.1:3333"
... }
... ]}})
{ "ok" : 1 }

4.设置仲裁服务器
新打开cmd,开启服务
D:\mongoDB\bin>mongod –dbpath F:\mongoDB\data –port 4444 –replSet shopex/127.0.0.1:2222
开启shell,设置及产看结果
H:\mongoDB\bin>mongo 127.0.0.1:2222/admin
shopex:PRIMARY> rs.addArb(“127.0.0.1:4444”)
{ “ok” : 1 }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
shopex:PRIMARY> rs.status()
{
"set" : "shopex",
"date" : ISODate("2017-03-20T05:55:12.742Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1489989307, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1489989307, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1489989307, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 1,
"name" : "127.0.0.1:2222",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 596,
"optime" : {
"ts" : Timestamp(1489989307, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-03-20T05:55:07Z"),
"electionTime" : Timestamp(1489989026, 1),
"electionDate" : ISODate("2017-03-20T05:50:26Z"),
"configVersion" : 2,
"self" : true
},
{
"_id" : 2,
"name" : "127.0.0.1:3333",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 296,
"optime" : {
"ts" : Timestamp(1489989307, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1489989307, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-03-20T05:55:07Z"),
"optimeDurableDate" : ISODate("2017-03-20T05:55:07Z"),
"lastHeartbeat" : ISODate("2017-03-20T05:55:11.766Z"),
"lastHeartbeatRecv" : ISODate("2017-03-20T05:55:10.786Z"
),
"pingMs" : NumberLong(0),
"syncingTo" : "127.0.0.1:2222",
"configVersion" : 2
},
{
"_id" : 3,
"name" : "127.0.0.1:4444",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 44,
"lastHeartbeat" : ISODate("2017-03-20T05:55:11.765Z"),
"lastHeartbeatRecv" : ISODate("2017-03-20T05:55:07.948Z"
),
"pingMs" : NumberLong(0),
"configVersion" : 2
}
],
"ok" : 1
}

现在如果关掉2222端口服务器,再打开,在执行rs.status(),可以看到2222的“stateStr”变成”SECONDARY”
“3333”的变成”PRIMARY”
相关链接