0%

mongodb入坑日志

 之前遇到个问我数据库的, 直接 没了解过-还在学习-不太清楚 素质三联怼上去…正好以后自己写扫描器的时候也得用, 是时候再攀一次科技树了.
 本文介绍如何安装mongodb, 以及如何使用python对数据库进行增删改查.

关于mongoDB

 mongoDB是一种NoSQL数据库, 基于文档对数据进行存储, 逻辑上的格式类似于json, 但是在硬盘中并不是真的以json进行存储, 数据被二进制序列化过, 也就是BSON.BSON的序列化和反序列化的性能都很高, 同时存储效率也不知道比json高到哪里去.

 mongodb的逻辑结构为层次结构, 由文档, 集合, 数据库三级构成. 和普通的关系型数据库的对应关系大致如下表

MySQL mongodb
一条记录 文档
集合
数据库 数据库

 mongodb的数据管理十分松散, 没有sql中对每个column的严格限制. 例如

1
2
3
{"age":20,"name":"张三","number":99731}
{"Date":"2020/06/04","weather":"Sunny"}
{"user":"admin","is_admin":true}

这三条数据是可以存到一个集合中的

mongdoDB 的安装

Linux 的情况

 在Linux中, 可以利用apt包管理器进行安装, 只需要简单的sudo apt install mongodb就可以. 在现阶段不需要修改config, 直接默认的配置就足以支持初期的学习. 安装完成后可以在命令行中键入mongo来连接本地的mongodb客户端.

Docker的情况

 当然, 也可也通过docker来拉一个mongodb的环境回来:

然后把容器的27017端口映射出来, 再在最后加上–auth参数, 告诉docker这个需要认证才能连接.

1
sudo docker run -itd --name mongo -p 27272:27017 mongo --auth

接下来由于数据库的管理员表是空的, 也就是说没办法从外面接入数据库. 所以需要走命令行接入容器中, 用命令行本地在mongodb中插入管理员的信息.

1
2
3
4
> sudo docker exec -it 9455 /bin/bash
# mongo
> use admin
> db.createUser({user:'root',pwd:'YourPWD',roles:[ { role: "root", db: "admin" } ] })

这样就在容器中插入一个超极管理员用户. 可以远程连接映射的端口来使用容器中的mongodb数据库.

python使用mongodb

 python有专门调用mongodb的包: pymongo. 安装也十分简单, pip install pymongo就行. 安装部分没什么好说的, 装完就能import, 有手就行.
 然后可以使用client=pymongo.MongoClient('mongodb://localhost:27017')来打开一个连接本地数据库的客户端client. 指定数据库使用db=client["db_name"], 指定集合的命令是collection=db['coll_name']. 感觉用起来就和用字典一样, 这也是mongodb的特点吧.
 如果使用的是远程的mongodb, 比如说上面搭建在docker里面的, 在连接的时候就需要使用pymongo.MongoClient('mongodb://{UserName}:{UserPass}@host:27017')来认证. 当然, 也可以先留空用户名和密码, 然后通过如下代码切到admin表来auth

1
2
3
moncli=pymongo.MongoClient('Host',port=27272)
au_db=moncli.admin
au_db.authenticate('UserName','PassWD')

 指定了集合后就可以开始愉快的增删改查. 具体等我明天起来再写, 先摸了.

 增加数据库和集合不需要额外的操作, 当向一个不存在的集合中插入数据的时候就会自动新建这个集合和数据库.
 python插入数据对应的方法是.insert_one.insert_many, 接受的参数分别是一个字典和一个字典组成的list. md写这段代码复现的时候还顺手复习一遍python的浅拷贝和深拷贝, 学到许多.jpg
 pymongo还支持一个.insert方法来插入数据, 它可以看作上面两个方法的集合, 传入list的时候就是_many, 传入dic的时候就是_one. 不过现在官方并不推荐使用这个方法.
这里我们用一个例子来说明, 下面这个脚本生成两段数据, 分别用insert_one和insert_many插入到test数据库的test_data集合中. 初始时是个空的数据库

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
import pymongo
import copy
moncli=pymongo.MongoClient('web.sern.site',port=1111)

au_db=moncli.admin
au_db.authenticate('root','YourPwd')

mongodb=moncli['test']
dbs=mongodb['test_data']
vulns=['ms17-010','CVE-2019-0708']
db=[]
datas={
'_id':0,
'ip':'',
'Vuln':[]
}

for i in range(1,10):
ip='192.168.1.'+str(i)
datas['_id']=i
datas["ip"]=ip
datas["Vuln"]=vulns
print(id(datas))
#db.append(datas)
db.append(copy.deepcopy(datas))
dbs.insert_many(db)
for i in range(11,20):
ip='192.168.2.'+str(i)
datas['_id']=i
datas['ip']=ip
datas["Vuln"]=vulns
dbs.insert_one(datas)

 执行上述脚本后, 可以看到test数据库和test_data这个集合被新建出来, 数据也被正确的插入库中.

 修改和删除都需要指定要修改和删除的对象, 查询是指定对象的手段. 在mongodb中, 有find_one()方法和find()方法分别用于查出一条符合的结果和查出所有符合的结果. 这两个方法的第一个参数是查询条件, 第二个参数是指定哪些查询结果能够被显示出来. 其中第一个参数支持正则匹配.

查询条件

 还是和sql语句对比着来看, 假设说现在有这么一个collection:

1
2
3
4
5
6

{'_id':1,'ip':'192.168.1.1','info':'vulnable'}
{'_id':2,'ip':'192.168.2.2','info':'notVulnable'}
{'_id':3,'ip':'192.168.2.3','info':'notVulnable'}
{'_id':4,'ip':'192.168.1.2','info':'vulnable'}
{'_id':5,'ip':'192.168.1.3','info':'vulnable'}
效果 sql mongodb
查询所有内容 select * from db db.find()
查询所有vulnable的数据 select * from db where info = “vulnable” db.find({“info”:”vulnable”})
查询所有ip在2.*的或者vulnable的数据 select * from db where info = "vulnabel" or ip="192.168.2.%" db.find({$or:[{"ip":{$regex:"192.168.2."} },{"info":"vulnabel"}]})

 除此之外, 大于小于这些操作符在mongodb中也有专门与之对应的实体:

操作 符号
大于 $gt
大于等于 $gte
小于 $lt
小于等于 $lte
不等于 $ne

 学习完如何查找文档, 就可以继续学习修改和删除. 修改和删除的重要一步就是指定要操作的数据. 在mongo中, 修改数据可以使用update_manyupdate_one来分别进行修改一个文档和修改所有匹配文档的操作. 这两个方法的第一个参数是上面的查询条件, 只有匹配这个条件的文档才会被修改. 第二个参数是要修改的值, 可以使用{$set:{key:value}}来特定的只修改某个键值对而不影响其它.

 pymongo使用delete_onedelete_many来分别负责删除一条和多条数据. 这两个方法需要一个参数, 来指定要删除的对象, 参数的规则和上面的搜索是一样的. 如果使用delete_many的同时不给任何参数, 就会删除集合中的所有文档.
 如果想要删除一个集合本身, 可以使用集合的drop方法. 类似的, 如果想把数据库整个删掉, 那就调用数据库对象的dropDatabase()方法就可以了. 从删库到跑路.