mongo速记一

一. 概述

就和描述里提到的一样,这次依旧是简单使用.crud以及聚合(管道)简单介绍.而且是基于单实例.写这个主要还是留作备份,以免以后长时间不用忘记了,到时候完整的看官方文档比较耗时间.所以这篇blog更多的是说明以及使用的一个例子.更多的option或者command不会列出,实际使用时可查寻官方文档~

当然这里的所有内容都可以在官网文档中找到~

二.素材准备

可以到官网下载server以及mongo shell

下载地址

三.安装以及数据库准备

我这边是debian,所以下载的是deb文件直接dpkg -i就可以了.
然后就是启动以及配置问题.很多选项都可以通过命令行的形式指定,但是这边还是建议通过配置文件来实现.默认的配置文件位于/etc/mongo.conf.这边可以复制出来修改使用.

首先是storage也是是数据存储部分.debian下默认是在 /var/lib/mongodb,自然可以根据自己的需求来配置,修改下图的dbPath即可

1
2
storage:
dbPath: /var/lib/mongodb

systemLog部分则是日志存储位置,同样依照自己的需求修改即可

1
2
3
4
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log

然后是通信的端口以及监听IP.这个和socket一样,可以选择本地还是内网还是公网.

1
2
3
net:
port: 27017
bindIp: 127.0.0.1

这是他的默认配置也就是说仅仅支持本地访问.如果需要的可以在后面继续添加,比如增加局域网访问

1
bindIp: 127.0.0.1,192.168.111.111

当然你也可以选择0.0.0.0 直接监听所有网络请求.

1
2
security:
authorization:enabled

这个则是开启用户认证的模块.(还有很多内容参见官网,比如fork,oplogSize等)

不过在开启之前需要新建一个用户,并且设置为admin用户,不然这个用户鉴权部分也就没有意义了.

新建用户:

1
db.createUser({user:"myAdmin",pwd:"xxxx",roles:[{role:"userAdminAnyDatabase",db:"admin"},{role:"dbAdmin",db:"admin"},{role:"clusterAdmin",db:"admin"}]})

这里简单说明下,userAdminAnyDatabase 则是赋予myAdmin用户所有db的用户管理权限,dbAdmin自然是管理自己的admin,clusterAdmin 则是集群的.这边如果遇到db.auth 认证日志出现两次结果,一次成功,一次replSet认证失败可以添加这个权限以继续下面的操作.

还有就是admin用户仅仅是管理功能,并不包含read 和 write 权限.
当然权限还有很多,具体的可以参考这个链接的文章.

现在创建一个新的测试库,use 一个不存在的库他会自动创建

1
use testdb

这时候其实在show dbs的时候 testdb是不可见的,只有在插入数据的时候才可见.

新建testdb的管理员:

1
db.createUser({user:"testdbAdmin",pwd:"xxxx",roles:[{role:"dbAdmin",db:"testdb"},{role:"dbOwner",db:"testdb"}]})

用户创建成功后就可以退出重新用testdb用户登录了:

1
2
use testdb
db.auth({user:"testdbAdmin",pwd:"xxxx"})

如果返回1就是认证成功了.

创建一个测试集合testC并插入第一条数据(同样不存在自动创建):

1
db.testC.insert({name:"first"})

如果返回WriteResult({“nInserted”:1})则说明插入成功了,这时候如果在另外一个mongo shell中myAdmin用户登录,查看所有数据库show dbs会发现testdb 已经可以正常显示了.

四.CRUD

插入:

1
2
3
db.collectionName.insert()
db.collectionName.insertOne({xxx:xxx})
db.collectionName.insertMany([{xxx:xxx},{xxx:xxx}])
1
2
db.testC.insertOne({name:"first"})
db.testC.insertMany([{name:"first"},{name:"second"},{name:"third"},{name:"toDelete"}])

如果没有指定_id字段,mongo则会自动生成该字段作为索引.(对于批量操作还有有序和无序之分,具体参见官方文档)

查询:

1
db.collectionName.find(<filter>,<projection>)

filter 是查询条件,projections是投影,其实是对数据做一些限制

1
2
// select * from testC
db.testC.find()
1
2
3
// select name from testC where name >= "third" or _id = ObjectId("5ce91317811bea15014713f5");
db.testC.find({$or:[{name:{$gte:"third"}},{_id:ObjectId("5ce91317811bea15014713f5")}]},{_id:0})

这条语句的大体意思和注释类似,其中_id:0 的意思是_id 字段不返回,其余类似or的还有and,类似gte的还有gt,lte,lt,ne,in等.

结果如下:

1
2
3
4
5
6
7
8
9
{
"name" : "first"
}
{
"name" : "third"
}
{
"name" : "todrop"
}

删除:

1
2
3
db.collectionName.deleteOne()
db.collectionName.deleteMany()
db.colletcionName.drop()

drop则是删除对应集合中的所有文档.

1
2
// delete from testC where name = "todrop"
db.testC.deleteOne({name:"todrop"})

更新

1
2
3
4
// db.collection.update( criteria, objNew, upsert, multi )
db.collectionName.updateOne(<filter>, <update>, <options>)
db.collectionName.updateMany(<filter>, <update>, <options>)
db.collectionName.replaceOne(<filter>, <update>, <options>)
1
2
3
4
// update testC set name = "1" where name = first
// updateOne 则是只更新一条.老版本是有update方法的,会有option true or false 指定更新一条还是多条 就是multi这个字段,upsert 则是指定未查询到时是否创建
db.testC.updateMany({name:"first"},{$set:{name:"1"}})

五.聚合

这个有点类似管道就是数据一轮一轮的处理

1
db.collectionName.aggregate(AGGREGATE_OPERATION)

这个这里也仅仅是提示下有这种用法,这是一个示例

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
db.collectionName.aggregate([
{
// filter1
$match:{
"_id":{$gte:ObjectId("xxx"),$lt:ObjectId("xxx")}
}
},
{
//filter2
$match:{
"field1":{$in:[
'111',
'222',
'333',
'444'
]
},
"field2":filedValue2
}
},
{
//aggregate
$group:{
_id:"$columnName",
count:{$sum:1},
alias1:{$sum:"$field3"},
alias2:{$sum:"$field4"}
}
}
])

这里简单说明下:这段语句的意思就是首先经过filter1的数据再经过filter2的过滤(先按照filter1的索引过滤这样第二个filter会快点),后面则是按照columnName字段分组,count:{$sum:1}则是统计行数作为count,这里$sum如果不指定字段则是统计行数,统计field3的和作为alias1的值,统计field4的和作为alias2的值

举个小例子
数据如下:

1
2
3
4
5
6
7
8
9
10
db.testC.insertMany(
[
{name:"first",age:1,city:"shanghai",score:90},
{name:"second",age:2,city:"shanghai",score:91},
{name:"third",age:3,city:"shanghai",score:92},
{name:"fourth",age:4,city:"nanjing",score:93},
{name:"fifth",age:5,city:"nanjing",score:94},
{name:"left",age:4,city:"unknow",score:100}
]
)

执行语句如下:其中5ce925cf10bc5eb4a70f8782是first的_id值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
db.testC.aggregate([
{
$match:{
"_id":{$gt:ObjectId("5ce925cf10bc5eb4a70f8782")}
}
},
{
$match:{"city":{$in:[
"shanghai",
"nanjing"
]}}
},
{
$group:{
_id:"$city",
count:{$sum:1},
ageSum:{$sum:"$age"},
scoreSum:{$sum:"$score"}
}
}
])

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
"_id" : "nanjing",
"count" : NumberInt(2),
"ageSum" : 9.0,
"scoreSum" : 187.0
}
{
"_id" : "shanghai",
"count" : NumberInt(2),
"ageSum" : 5.0,
"scoreSum" : 183.0
}

六.补充

这里很多内容没有涉及,例如索引以及事务副本集等.均可以参考官方文档.还有就是可以通过部分可视化工具简化操作例如mongochef等

客官扫码领红包哟~