MongoDB 进阶操作
先来讲一下聚合查询
聚合查询
db.< collection >.aggregate(
[
{管道1},
{管道2}
]
)
总的来说,聚合查询就是通过管道,来实现对上一次数据的… 承接?? 先用这个词吧,比较直观形象。
先把数据插入进去 下面图片里的数据不太好,插入这个。
db.stus.insert([
{name:"小华",age:12,gender:"男",like:"ji"},
{name:"小明",age:14,gender:"男",like:"mao"},
{name:"小红",age:19,gender:"男",like:"gou"},
{name:"小蓝",age:19,gender:"男",like:"ji"},
{name:"小明",age:14,gender:"女",like:"mao"},
{name:"小红",age:19,gender:"女",like:"gou"},
{name:"小蓝",age:19,gender:"女",like:"ji"},
{name:"小花",age:13,gender:"男",like:"mao"}
])
$group 分组操作
按性别分组
db.stus.aggregate([{$group:{_id:"$gender"}}])
一些操作的表达式: $sum $avg $first $last $max $min $push
分组求年龄之和
db.stus.aggregate(
[
{$group:{_id:"$gender",sumage:{$sum:"$age"}}}
])
求年龄的平均值
db.stus.aggregate(
[
{$group:{_id:"$gender",avgage:{$avg:"$age"}}}
])
求年龄最大值
db.stus.aggregate(
[
{$group:{_id:"$gender",max_age:{$max:"$age"}}}
])
求最小值
db.stus.aggregate(
[
{$group:{_id:"$gender",min_age:{$min:"$age"}}}
])
看第一个
db.stus.aggregate(
[
{$group:{_id:"$gender",first_one:{$first:"$age"}}}
])
看最后一个
db.stus.aggregate(
[
{$group:{_id:"$gender",last_one:{$last:"$age"}}}
])
按性别看一下名字都有哪些
db.stus.aggregate(
[
{$group:{_id:"$gender",nameall:{$push:"$name"}}}
])
刚才看看了分组,下面我们看看其他的管道
$match 匹配
查找 和find作用一样,不过它是管道
查找年龄大于12的 男女年龄的平均值
db.stus.aggregate([
{$match:{age:{$gte:12}}},
{$group:{_id:"$gender",avgage:{$avg:"$age"}}}
])
管道的作用就是把第一个筛选完的结果传递给第二个,我这个数据不是很好,
$project 投影
显示的 是1 或者true
求年龄小于50,按照喜好分组求年龄的和和年龄的平均值
db.stus.aggregate([
{$match:{age:{$lt:19}}},
{$group:{_id:"$like",sumage:{$sum:"$age"},avgage:{$avg:"$age"}}},
{$project:{sumage:1}}
])
$sort 排序
db.stus.aggregate([
{$match:{age:{$lt:19}}},
{$group:{_id:"$like",sumage:{$sum:"$age"},avgage:{$avg:"$age"}}},
{$project:{sumage:1}},
{$sort:{_id:-1}}
])
$skip 和 $limit
db.stus.aggregate([
{$limit:4},
{$skip:2}
])
$skip 和 $limit
db.stus.aggregate([
{$skip:2},
{$limit:4}
])
我们会发现,这次换位置后得到的结果不一样,因为管道会把上一个筛选过的数据传给下一个管道,
$unwind 拆分列表
db.stus.aggregate([
{$group:{_id:"$gender",nameall:{$push:"$name"}}},
{$unwind:"$nameall"}
])
把一个列表拆成几个单独的列表
对大量数据的操作
在示例中,我们插入的数据都很少,但是事实上,我们的数据都是上千上万的,下面就来看看大量数据的操作
插入20000个,用for循环
for(var i=0;i<20000;i++){
db.numbers.insert({
_id:i,user:"user"+i,age:i
})
}
我们发现运行这个后,光标一直在闪,这是插入数据比较慢,一直在运行。
下面我们我们查找_id,user,age,一样的数据,看看时间
db.numbers.find({_id:5555}).explain('executionStats') //0毫秒
db.numbers.find({user:"user5555"}).explain('executionStats')//12毫秒
db.numbers.find({age:55555}).explain('executionStats') //6
这个不同电脑不太一样,但是我发现按id查询快,按其他的都比较慢,这是我数据少体现的不明显,有兴趣的可以插入500000条看看,差别就大了。
下面我们看看如何来改进,我们已经发现,按id查速度比较快,因为id是这个集合的默认索引,但实际开发的时候,我们并不会手动设置id,所以我们要想办法把索引改为其他的,比如说 改为 内容的key,
db.numbers.ensureIndex({user:1}) //修改 添加索引
db.numbers.find({user:"user5555"}).explain('executionStats')//再查一下
我们一般用完就把我们设置的索引删了。
![](/qrcode.jpg)
查看索引:
db.numbers.getIndexes()
后来添加的索引,主要是名字和我们添加的不一样了,我添加的索引名字是user 但变成了user_1,始计算,我们加的都会有这个下划线和1.
删除索引
db.numbers.dropIndex("user_1")
主要的索引是不能删的,必须有
备份和恢复数据库
下面的四个操作需要 重新打开一个cmd 因为这个是不同的任务,mongo不认识这个指令,但原来操作mongo的也不要关啊,我们还要验证操作有没有成功。
备份数据库 图中有解释 这是我的路径
mongodump -h 127.0.0.1:27017 -d test -o \MongoDB\data\dump
备份完了看看
恢复数据库
mongorestore -h 127.0.0.1:27017 -d testttt --dir D:\MongoDB\data\dump\test
导出和导入数据库
我们可以导出json 和 csv 两种格式
1.json
mongoexport -h 127.0.0.1:27017 -d testttt -c numbers -o D:\MongoDB\data\dump\data.json
2.csv
mongoexport -h 127.0.0.1:27017 -d testttt -c numbers -o D:\MongoDB\data\dump\data.csv --type csv -f _id,user,age
csv 需要你指明 需要导出的字段,就我这里导出 _id,user,age, 还有告诉导出的文件类型就是 csv 比json麻烦一些
导入数据库
mongoimport -h 127.0.0.1:27017 -d heihei -c numbers --file D:\MongoDB\data\dump\data.json
python 和 mongo 的故事
先要安装,pip install pymongo
一直看我博文的小伙伴应该已经切换好了国内源,如果没有切换好的 看看 pip 切换国内源
下面直接看操作,当然我们要先自己吧服务启动起来,然后再执行下面的操作,由于没有什么特别的内容,大家可以自己执行下面的操作,然后打开mongo 看看有没有把数据 增删改查成功, 我这里就不一一截图了,其实结果和我们直接操作mongo 是一样的。
- 连接mongod 的服务
import pymongo
# pymongo.MongoClient(host='localhost', port=27017) 一般第一个传host 第二个传port 但不传也可以
mongo_py = pymongo.MongoClient()
- 建立数据库和集合
# 建立数据库 同样当其中有数据就会自动建立,我们现在的建立其实是提前告诉数据库和表的名字
# 和可以用 mongo.pytest 来建立
db = mongo_py['pytest']
# 建立集合
collection = db['stu']
# collection = mongo_py.pytest.stu 也可以通过这个一次性建立数据库和表,
- 插入数据
# 插入一个数据
one = {"name": "xiaoxiao", "age": 16}
# 插入多个数据
tow_many = [
{"name": "Vpa", "age": 16},
{"name": "Joe", "age": 16},
{"name": "Timi", "age": 13},
{"name": "Jerry", "age": 14},
{"name": "Vees", "age": 16},
{"name": "Xeceo", "age": 16},
{"name": "Mona", "age": 14},
{"name": "Gen", "age": 17},
{"name": "Boo", "age": 19},
{"name": "Loce", "age": 18},
{"name": "Yae", "age": 19}
]
# 插入
result1 = collection.insert_one(one)
result2 = collection.insert_many(tow_many)
# result = collection.insert() 这个可以插入多个也可以插入一个
- 删除
result = collection.delete_one({"age":19})
result = collection.delete_many({"age": 14})
- 修改数据
result1 = collection.update_one({"age":16},{"$set":{"name":"xiao"}})
result2 = collection.update_many({"age":16},{"$set":{"name":"xiao"}})
- 查询
result = collection.find({"age": 16})
for i in result:
print(i)
## find()返回的是对象,我们遍历打印里面的内容
result1 = collection.find_one({"age":19})
# find_one()返回的直接就是一个内容
print(result1)
- 关闭数据库
mongo_py.close()
完整的,我们可以把这些写在try except finally 里, 最后不管成功与否,我们都是要关闭数据库的。
总结一下:
今天 我们学习了 对mongo 的管道操作和 数据的导入导出,备份恢复。
而用python 操作mongo 实际上是连接到了本地的MongoDB,构建了一个数据库和集合,之后,都是通过 该集合的方法来操作,而且与直接在mongo中操作差别不大,使用的方法名称也没有大的变化,主要python 里面都是要用引号的,不然不认识
mongo用python 操作还要很多其他的方法,但是爬虫里我们主要用的就是插入,然后统计一下有多少个,如果有兴趣的朋友可以去看看pymongo这个库的代码,里面还有其他方法,而且都有注释。有一说一,有的不常用的我也不知道 (卑微)
今天讲的挺多的,估计 30 分钟学不完了(滑稽) ,明天停更一下,博主要线上测试 数电 和 模电 了 ,我考完了,哈哈哈。
后面要学习的还是 数据库(小声),是 数据存储-redis大家可以先安装一下redis。
我又来要赞了,如果觉得讲的还算详细,点个赞再走吧,欢迎各位大佬评论指出问题,如果有什么问题也欢迎评论,私聊,关注点上,我们一起学习。