每天30分钟 一起来学习爬虫——day14(数据存储 之 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')//再查一下

在这里插入图片描述
我们一般用完就把我们设置的索引删了。

扫描二维码关注公众号,回复: 10558745 查看本文章
查看索引:
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 是一样的。

  1. 连接mongod 的服务
import pymongo
    # pymongo.MongoClient(host='localhost', port=27017) 一般第一个传host 第二个传port 但不传也可以
    mongo_py = pymongo.MongoClient()
  1. 建立数据库和集合
   # 建立数据库 同样当其中有数据就会自动建立,我们现在的建立其实是提前告诉数据库和表的名字
    # 和可以用 mongo.pytest 来建立
    db = mongo_py['pytest']
    # 建立集合
    collection = db['stu']
    # collection = mongo_py.pytest.stu 也可以通过这个一次性建立数据库和表,
  1. 插入数据
  	# 插入一个数据
  	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() 这个可以插入多个也可以插入一个
  1. 删除
result = collection.delete_one({"age":19})
result = collection.delete_many({"age": 14})
  1. 修改数据
result1 = collection.update_one({"age":16},{"$set":{"name":"xiao"}})
result2 = collection.update_many({"age":16},{"$set":{"name":"xiao"}})
  1. 查询
result = collection.find({"age": 16})
for i in result:
    print(i)
## find()返回的是对象,我们遍历打印里面的内容
result1 = collection.find_one({"age":19})
# find_one()返回的直接就是一个内容
print(result1)
  1. 关闭数据库
 mongo_py.close()

完整的,我们可以把这些写在try except finally 里, 最后不管成功与否,我们都是要关闭数据库的。


总结一下:
今天 我们学习了 对mongo 的管道操作和 数据的导入导出,备份恢复。

而用python 操作mongo 实际上是连接到了本地的MongoDB构建了一个数据库和集合,之后,都是通过 该集合的方法来操作,而且与直接在mongo中操作差别不大,使用的方法名称也没有大的变化,主要python 里面都是要用引号的,不然不认识

mongo用python 操作还要很多其他的方法,但是爬虫里我们主要用的就是插入,然后统计一下有多少个,如果有兴趣的朋友可以去看看pymongo这个库的代码,里面还有其他方法,而且都有注释。有一说一,有的不常用的我也不知道 (卑微)

今天讲的挺多的,估计 30 分钟学不完了(滑稽) ,明天停更一下,博主要线上测试 数电 和 模电 了 ,我考完了,哈哈哈。
后面要学习的还是 数据库(小声),是 数据存储-redis大家可以先安装一下redis。


我又来要赞了,如果觉得讲的还算详细,点个赞再走吧,欢迎各位大佬评论指出问题,如果有什么问题也欢迎评论,私聊,关注点上,我们一起学习。

发布了57 篇原创文章 · 获赞 61 · 访问量 5485

猜你喜欢

转载自blog.csdn.net/weixin_45691686/article/details/105181900
今日推荐