Python视频学习(二十、mongodb)

1. 安装

2. 基本命令

2.1 数据库和集合命令

数据库基本命令
db查看当前所在的数据库
show dbs/ show databases查看所有数据库
use 数据库名切换数据库
db.dropDatabase()删除当前所在的数据库

集合collection相当于关系型数据库的表,也是不必须手动创建,当第一次插入数据的时候就会创建了

显示创建集合命令
db.createCollection(name,options)
db.createCollection("memeda")创建名字为 memeda 的集合
db.createCollection("memeda", { capped: true, size: 10} )创建memeda集合,并且限制大小,最大为10字节,超过之后就会 新来的数据覆盖最早的数据
基本集合命令
show collections显示当前数据库中所有的集合
db.集合名.drop()删除集合

2.2 mongodb数据类型

  • Object ID: ⽂档ID
  • String: 字符串, 最常⽤, 必须是有效的UTF-8
  • Boolean: 存储⼀个布尔值, true或false
  • Integer: 整数可以是32位或64位, 这取决于服务器
  • Double: 存储浮点值
  • Arrays: 数组或列表, 多个值存储到⼀个键
  • Object: ⽤于嵌⼊式的⽂档, 即⼀个值为⼀个⽂档
  • Null: 存储null
  • Timestamp: 时间戳, 表示从1970-1-1到现在的总秒数
  • Date: 存储当前⽇期或时间的UNIX时间格式
Date类型的使用

对应python的 datetime类型

new Date('2017-12-20')  // 17年12月
new Date(2018,0,1)    // 18年1月1日
ObjectId
  • 每个⽂档都有⼀个属性, 为_id, 保证每个⽂档的唯⼀性
  • 可以⾃⼰去设置_id插⼊⽂档,如果没有提供, 那么MongoDB为每个⽂档提供了⼀个独特的_id, 类型为objectID
  • ObjectID是⼀个12字节的⼗六进制数:
    • 前4个字节为当前时间戳
    • 接下来3个字节的机器ID
    • 接下来的2个字节中MongoDB的服务进程id
    • 最后3个字节是简单的增量值

2.3 基本数据命令

CRUD数据基本命令
db.集合名.insert( document )插入数据(document是一个json
db.集合名.save(document)保存, 如果_id在collection中已经存在则修改,否则插入新数据
db.集合名.find()返回集合内的所有数据
db.集合名.update( 查询条件,更新后结果, {multi: false})根据查询条件匹配,更新数据,默认更新一条
db.集合名.remove(查询条件, {justOne: false})根据查询条件删除数据,默认删除多条匹配

a. 插入

db.集合名.insert( document )

示例:

db.stu.insert({name:'gj',gender:1})
db.stu.insert({_id:"20170101",name:'gj',gender:1})

如果插入的document不包含 _id,则mongo会自动设置一个文档id字段_id,类型为ObjectId

b. 保存

db.集合名.save(document)

插入+修改。 如果document中有_id,并且collections中也有对应的数据,那么就会修改原数据;否则插入新数据

示例:

db.mongodemo.save({_id:"123456789", name:"zhouwang", age:17 })

c. 简单查询

db.集合名.find()

d. ★更新

db.集合名称.update(<query> ,<update>,{multi: <boolean>})
  • 参数query:查询条件
  • 参数update:更新操作符
  • 参数multi:可选, 默认是false,表示只更新找到的第⼀条记录, 值为true表示把满⾜条件的⽂档全部更新

示例:

# 将第一条匹配的 name为zhouwang的,更新为 age为20
# 注意--> 这会完全替换,除了 _id保留,其他属性只剩下了  age:20
db.mongodemo.update({name:"zhouwang"}, {age:20})  

# 使用$set 能够指定部分更新,而不是全部替换
db.mongodemo.update({name:"zhouwang"},{$set:{ age:30, gender:"male"}   })

# 同时更新多条
db.mongodemo.update({name:"zhouwang"}, {$set: {age:20}}, {multi:true})  

e. ★删除

db.集合名称.remove(<query>,{justOne: <boolean>})
  • 参数query:可选,删除的⽂档的条件
  • 参数justOne:可选, 如果设为true或1, 则只删除⼀条, 默认false, 表示删除多条

3. 高级查询

方法
db.集合名.find( 条件 )
db.集合名.findOne( 条件 )
db.集合名.find( 条件).pretty()

比较运算符

运算符示例
$lt小于db.mongodemo.find({age: {$lt: 26} })
$lte小于等于
$gt大于
$gte大于等于
$nt不等于

判断年龄年龄范围的写法是:

db.mongodb.find({ age : {$gt: 20} },  age : {$lt: 40})

范围运算符

运算符示例
$in在范围内
$nin不在范围内db.mongodemo.find({ name: { $nin : [ "haha", "a", "b"] } })

逻辑运算符

  • 与 —— 直接写多个条件
db.mongodemo.find( {name : "hsy", age :{$lt: 30}} )
  • or —— $or
db.mongodemo.find( { $or: [{name : "hsy"}, { age :{$lt: 30}} ] } )

正则

  1. //里面写正则:db.集合名.find( {name : /^abc/} )
  2. 使用$regexdb.集合名.find( { name : {$regex: "^abc" }} )

分页操作

运算符示例
db.集合名.find().limit(n)拿几个
db.集合名.find().skip(n)跳过几个db.mongodemo.find().skip(3).limit(2)

建议先skip再limit

自定义条件

  • $where
    • 自己定义函数,返回true
    • 可以使用this访问到每条数据
db.集合名.find({
	$where: function(){
		if this.age < 18;
			return true;
	}
})

投影

db.集合名.find(条件, 投影字段)

控制哪条返回,哪条不返回

  • 1代表显示,0代表不现实
  • _id字段默认显示
  • 不要混合使用 1 和 0,否则会报错
db.stu.find({条件},  { _id: 0, _sex: 0, name: 0})

排序

  • db.集合名.find().sort({排序字段})
    • 1代表正序, -1代表逆序
db.stu.find.sort( age: -1, gender: 1})

统计个数

  • db.集合名.count(条件)
  • db.集合名.find({条件}).count()

去重

  • db.集合名.distinct(字段名, 条件)

db.集合名.distinct("name", {age: 40} )

4. 聚合

聚合是基于数据处理的聚合管道, 每个文档(数据)通过一个 由** “多阶段”组成的管道**, 可以多每个阶段的管道进行分组、过滤、匹配等操作,最后输出结果

语法:

db.集合名.aggregate(
	{管道:  { 表达式 }  },
	{管道:  { 表达式 }  },
	...
)

在这里插入图片描述

常用管道说明
$group分组,可用于统计结果—— group by null 可以返回所有
$match按照条件匹配数据,用于过滤
$project投影, 修改文档结果
$sort排序
$skip跳过指定数量的文档,并且返回其他的
$limit限制返回的文档数目
$ unwind将数组类型的字段进行拆分
常用表达式说明
$sum计算和 —— $sum:1 可以用于统计数目
$avg
$min
$max
$push在结果文档中插入一个值到数组中
$first获取第一个文档结果
$last获取最后一个文档结果

4.1 $group

  • $group对应的字典中有几个键,结果中就有几个键
  • 使用 _id 指定按照哪个分组
  • 聚合使用的列名前都要加上$
  • 能够同时按照多个键进行分组{$group:{_id:{country:"$country",province:"$province"}}}
    • 结果是:{_id:{country:"",province:""}

案例

  1. 将结果按照 age 分组:
db.mongodemo.aggregate({$group: {_id: "$age" } })

>
{"_id":30}
{"_id":26}
{"_id":52}
  1. 将结果按照age分组,并且显示组每组有多少人
db.mongodemo.aggregate({$group: {_id: "$age", count:  {$sum:1}  } })

{"_id":30, "count":  1 }
{"_id":26, "count":  2}
{"_id":52, "count":  1}
  1. 按照性别分类,然后 输出获取平均值
db.mongodemo.aggregate( {$group:  { _id: "$gender",  avg_age: {$avg : "$age"}  } } )
  1. 把所有数据作为一组,计算
db.mongodemo.aggregate( {$group:  { _id: null,  count: {$sum:1},  avg_age: {$avg : "$age"}  } } )
  1. 按照age分组,然后将每个数据的name值显示成列表
db.mongodemo.aggregate({$group:  {_id:"$age", names:{ $push: "$name"  } } })

4.2 $project

  • 每一个管道处理都是 aggregate的一个参数
  • 上一个管道的结果将作为下一个管道的输入

在这里插入图片描述

案例

  1. 按照gender进行分组,获取不同组数据的个数和平均年龄
db.stu.aggregate(
  {$group:{_id:"$gender",count:{$sum:1},avg_age:{$avg:"$age"}}},
  {$project:{gender:"$_id",count:1,avg_age:"$avg_age",_id:0}}
  )

4.3 $match

  • 用来过滤,聚合内不能使用find

案例

  1. 选择年龄大于20的学生,观察男性和女性有多少人
db.stu.aggregate(
  {$match:{$or:[{age:{$gt:20}},{hometown:{$in:["蒙古","⼤理"]}}]}},
  {$group:{_id:"$gender",count:{$sum:1}}},
  {$project:{_id:0,gender:"$_id",count:1}}
  )

4.4 $sort

在这里插入图片描述

4.5 skip 和 limit

limit描述

在这里插入图片描述

4.6 $unwind

  • 将文档的某一个数组类型的字段拆分出来 变成多条文档

案例

  1. 数据库有一个:{"username":"Alex", "tags": ["C#", "Java", "C++"] } , 获取该tag数组的长度:
db.mongodbdemo.aggregate( 
{$match:  { username: "Alex" } } ,
{$unwindw :  "tags"}
{$group: {_id:null,  count :  {$sum:1 }} }
)
  1. 防止没有该字段、字段为空数组、字段为""的数据丢失

在这里插入图片描述

5. 数据备份和还原

  • 备份:

在这里插入图片描述

  • 还原

在这里插入图片描述

6. 索引

目的: 提高查询速度

  • 查询命令花费的时间: db.xxx.find().explain('executionStats)
  • 默认_id字段是有索引的
命令说明
db.集合名.ensureIndex({属性: 1或者-1})建立索引
db.集合名.ensureIndex({属性: 1或者-1}, {"unique": true})建立唯一索引
db.集合名.ensureIndex({属性: 1或者-1}, {"unique": true, "dropDups": true})建立唯一索引并且丢弃重复
db.集合名.ensureIndex({属性1:1, 属性2:1 })建立联合索引
db.集合名.getIndexes()查看当前集合的所有索引
db.集合名.dropIndex("索引字段名")删除索引
  • 1代表升序, -1代表降序(除非需要升序或者降序操作,否则1或者-1区别不大)

7. 数据去重思路

爬虫数据去重,实现增量式爬虫

方法: 使用数据库建立关键字段(一个或者多个)建立索引进行去重

  1. 根据url地址进行去重
    使用场景:url地址对应的数据不会变的情况,url地址能够唯一判别一个条数据的情况

     1. 使用redis的集合
     2. 布隆过滤器
         - 使用多个加密算法加密url地址,得到多个值
         - 往对应值的位置把结果设置为1
         - 新来一个url地址,一样通过加密算法生成多个值
         - 如果对应位置的值全为1,说明这个url地址已经抓过
         - 否则没有抓过,就把对应位置的值设置为1
    
  2. 根据数据本省进行去重—— 加密后放入redis的集合中

    选择特定的字段,使用加密算法(md5,sha1)讲字段进行假面,生成字符串,存入redis的集合中. 后续新来一条数据,同样的方法进行加密,如果得到的字符串在redis中存在,说明数据存在,对数据进行更新,否则说明数据不存在,直接插入

8. Python操作mongodb

官方文档

from pymongo import MongoClient

client = MongoClient(host="192.168.1.162", port=27017)   # 会自动去连接
collection = client.数据库名.集合名

# 插入
objId = collection,insert({"name":"哈哈", "age":100})  # 插入,会自动创建 _id
print(objId)  # 插入操作会返回 _id

objIds = collection.insert_many([{},{},{}])  # 插入多条,效率更高

# 删除
collection.delete_one({"name":"哈哈"})
collection.delete_many({"name":"哈哈"})

# 查找
cursor = collection.find()   # 返回一个cursor
for data in cursor:
	print(data)
	
collection.find_one({"name":"哈哈"})    # 返回一条数据

# 更新
collection.update_one({"name":"哈哈"}, {"$set": {"name":"yy"} }  )
collection.update_many({"name":"哈哈"}, {"$set": {"name":"yy"} }  )
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值