爬虫数据存储相关的数据库MongoDB
关系型数据库
MySQL、oracle、acess、db2、postgresql、sqlite...
1.存储数据基本都是以表格为基本形式
2.表与表之间可以建立关系(外键)
非关系型数据库
redis、mongodb、memcache
1.数据基本都是以key:value键值对的形式存储
2.没有明确的表结构限制
"""
主库一般情况下都是关系型数据库
从库一般情况下都是非关系型数据库
从库一般情况下较于主库数据的存取速度都比较快
"""
持久化
肯定跟数据库相关
因为持久化就是用数据库来长期的保存数据
MongoDB简介
1.是爬虫爬取数据之后首选的一款数据持久化软件
2.最像关系型数据库的文档型非关系型数据库
1.下载安装的时候
如果是压缩包的形式,那么解压之后只有一个bin文件夹
你需要自己创建一个data文件夹和log文件夹
2.将mongo.exe和mongod.exe所在的路径添加到环境变量中
3.执行以下安装系统服务的命令
mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install
上述命令完成后只会将MongoDB添加到系统服务里面并没有启动
4.启动服务
net start MongoDB # 手动找到服务启动也可以
# 停止服务
net stop MongoDB
5.上述的系统服务制作类似于MySQL以跳过授权表的方式启动服务端
mysqld --skip-grant-tables
# 如何让mongodb也校验用户名和密码
先停止服务
net stop MongoDB
移除
mongod --remove
重新制作系统服务
mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install --auth
启动系统服务
net start MongoDB
6.MongoDB每一个库都可以创建用户名和密码 并且创建的用户名和密码都是普通用户
如果你想要创建管理员用户就必须去admin库下创建才可以
7.创建管理员用户
'''涉及到用户登录认证 引号最好统一都用双引号'''
use admin # 切换到admin下
db.createUser(
{
user: "root",
pwd: "123",
roles: [ { role: "root", db: "admin" } ]
}
)
8.让MongoDB以校验用户身份启动
mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\Server\4.2\log\mongod.log --logappend --dbpath D:\MongoDB\Server\4.2\data --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install --auth
net start MonoDB
mongo进入服务端之后发现没有很多权限
需要验证身份
这个用户在哪个库下面创建的就必须切换到哪个库下面去做验证
9.创建普通用户
use test
db.createUser(
{
user: "jason",
pwd: "123",
roles: [ { role: "readWrite", db: "test" },
{ role: "read", db: "db1" } ]
}
)
# 删除创建的用户
db.dropUser(username) # 用户在哪个库下面创建的 之后针对该用户的操作都必须切换到该库下
10.也可以直接使用用户名和密码方式登录
mongo --port 27017 -u "root" -p "123" --authenticationDatabase "admin"
"""
在mongodb中所有的命令都可以采用.help()的形式查看具体的使用说明
"""
数据库的增删改查语句
# 查看当前所在的库名
db
# 切换库|增库
# 库不存在直接创建 库存在则切换
use 库名
'''
创建出来的库使用show dbs是无法直接看到的
因为这个库目前里面什么数据都没有 其实是创建在内存中的还没有保存到硬盘上
'''
# 查看所有库
show databases
show dbs
# 删库
# 先切换到该库下 然后删
use 库名
db.dropDatabase()
collections集合操作(表操作)
# 查看当前库中所有的表
show tables
# 增加表
use 库名 # 先进入库
db.表名.insert({'a':1,'b':2}) # 表不存在会自动创建,insert就是往表中添加数据
db.表名.insert({'a':111,'b':222,'c':333}) # 键值对的个数每次都可以不一样
# 删除表
db.表名.drop()
document文档操作(记录操作)
增
# 插入单条 insert({})
t10={"name":"a","age":10,'hobbies':['music','read','dancing']}
db.t1.insert(t10)
db.t1.find()
# 插入多条 insertMany([{},{},{},{}])
t11={"_id":1,"name":"a","age":10,'hobbies':['music','read','dancing']}
t12={"_id":2,"name":"b","age":20,'hobbies':['music','read','run']}
t13={"_id":3,"name":"c","age":30,'hobbies':['music','drink']}
t14={"_id":4,"name":"d","age":40,'hobbies':['music','read','dancing','tea']}
t15={"_id":5,"name":"e","age":50,'hobbies':['music','read',]}
db.t1.insertMany([t11,t12,t13,t14,t15])
db.t1.find()
查
db.表名.find() # 查询当前表中所有的数据
findOne() # 只拿匹配到的第一个数据
"""
mongoDB会自动给每个数据项添加一个主键字段
_id: ObjectId('23432h234j24234j') # 自动创建的唯一编号
如果你自己给了_id字段 那么则不会再自动创建了
"""
db.表名.find({'a':1}) # 查询含有a:1键值对的数据
# 详细操作
#1、查看既有dancing爱好又有tea爱好的人
# $all类似于是and关系
db.t1.find({'hobbies':{"$all":['dancing','tea']}})
#2、查看第4个爱好为tea的人(索引为依据)
db.t1.find({"hobbies.3":'tea'})
#3、查看所有人的第2个到第3个爱好
db.t1.find({},{'hobbies':{"$slice":[1,2]},"age":0,"_id":0,"name":0,"addr":0})
# 键后面的值是0表示查询的时候不要这些键对应的数据
#4、将数据以标准的格式展示出来
db.t1.find().pretty()
#5、取指定的字段数据
#SQL:select name,age from db.t1 where id=3;
db.t1.find({'_id':3},{'_id':0,'name':1,'age':1})
运算符
# SQL:=,!=,>,<,>=,<=
# MongoDB:{key:value}代表什么等于什么,"$ne","$gt","$lt","gte","lte",其中"$ne"能用于所有数据类型
#1、select * from db1.t1 where name = "a";
db.t1.find({'name':'a'}) # =
#2、select * from db1.t1 where name != "a";
db.t1.find({'name':{"$ne":'a'}}) # $ne : not equal(!=)
#3、select * from db1.t1 where id > 2; # $gt : >
db.t1.find({'_id':{'$gt':2}})
#4、select * from db1.t1 where id < 3; # $lt : <
db.t1.find({'_id':{'$lt':3}})
#5、select * from db1.t1 where id >= 2; # $gte : >=
db.t1.find({"_id":{"$gte":2,}})
#6、select * from db1.t1 where id <= 2; # $lte : <=
db.t1.find({"_id":{"$lte":2}})
逻辑运算
# SQL:and,or,not
# MongoDB:字典中逗号分隔的多个条件是and关系,"$or"的条件放到[]内,"$not"
# 字段是键 连接符和条件单独放值的字典
#1、select * from db1.t1 where id >= 2 and id < 4;
db.t1.find({'_id':{"$gte":2,"$lt":4}})
#2、select * from db1.t1 where id >= 2 and age < 40;
db.t1.find({"_id":{"$gte":2},"age":{"$lt":40}})
#3、select * from db1.t1 where id >= 5 or name = "a";
db.t1.find({"$or":[{'_id':{"$gte":5}},{"name":"a"}]})
#4、select * from db1.t1 where id % 2=1;
db.t1.find({'_id':{"$mod":[2,1]}})
#5、上题,取反
db.t1.find({'_id':{"$not":{"$mod":[2,1]}}})
成员运算
# SQL:in,not in
# MongoDB:"$in","$nin"
#1、select * from db1.t1 where age in (20,30,31);
db.t1.find({"age":{"$in":[20,30,31]}})
#2、select * from db1.t1 where name not in ('a','b');
db.t1.find({"name":{"$nin":['a','b']}})
正则运算
# SQL: regexp 正则
# MongoDB: /正则表达/i
#1、select * from db1.t1 where name regexp '^a.*?(g|n)$';
db.t1.find({'name':/^a.*?(g|n)$/i})
排序
# sql:asc desc
# 排序:1代表升序,-1代表降序
db.t1.find().sort({"name":1,})
db.t1.find().sort({"age":-1,'_id':1})
限制数据展示条数
# 分页:limit代表取多少个document,skip代表跳过前多少个document。
# select * from t1 order by age limit(2,1)
db.t1.find().sort({'age':1}).limit(1).skip(2)
# 获取数量
db.t1.count({'age':{"$gt":30}})
删
# 删除多个中的第一个 deleteOne({})
db.t1.deleteOne({'age': 8 })
# 删除所有 deleteMany({})
# 删除所有年龄为8岁的
db.t1.deleteMany({ 'age': 8 }) # SQL:delete from t1 where ...
#3、删除全部
db.t1.deleteMany({}) # SQL:delet from t1;
改
覆盖式
# update就类似于是将原来的数据完完全全的重新写一份 效率较低
# 注意:除非是删除,否则_id是始终不会变的
db.t1.update({'_id':1},{"name":"z","hobbies_count":3})
# 是用{"_id":1,"name":"z","hobbies_count":3}覆盖原来的记录
'''
你可以将查询出来的一个个数据看成是一个个对象
然后可以利用对象点点点的操作来获取数据和修改数据
'''
var obj=db.t1.findOne({"_id":1})
obj.t1name=obj.name+'!'
delete obj.age
db.t1.update({"_id":1},obj)
设置$set
# $set 哪里需要修改就针对性的改哪里
#1、SQL:update db1.t1 set name="X" where id = 2
db.t1.update({'_id':2},{"$set":{"name":"X",}})
#2、没有匹配成功则新增一条{"upsert":true}
db.t1.update({'_id':6},{"$set":{"name":"f","age":18}},{"upsert":true})
#3、默认只改匹配成功的第一条,{"multi":改多条}
db.t1.update({'_id':{"$gt":4}},{"$set":{"age":28}})
db.t1.update({'_id':{"$gt":4}},{"$set":{"age":38}},{"multi":true})
'''
看似字典的数据其实是对象
并且这个对象比我们python面向对象里面的对象还要灵活
既可以点键
也可以点索引值
'''
#4、把名字为e的人的第2个爱好改成piao
db.t1.update({'name':"e"},{"$set":{"hobbies.1":"piao"}})
#5、删除e的爱好,$unset
db.t1.update({'name':"e"},{"$unset":{"hobbies":""}})
增加与减少$inc
#1、所有人年龄增加一岁
db.t1.update({},{"$inc":{"age":1}},{"multi":true})
#2、所有人年龄减少5岁
db.t1.update({},{"$inc":{"age":-5}},{"multi":true})
元素的添加删除
#添加删除数组内元素
"""
push python列表中append
pop python列表中pop
pull python列表中remove
$each 后面跟一个列表 类似于python中的for循环
"""
# 往数组内添加元素:$push
#1、为名字为c的人添加一个爱好read
db.t1.update({"name":"c"},{"$push":{"hobbies":"read"}})
#2、为名字为c的人一次添加多个爱好tea,dancing
db.t1.update({"name":"c"},{"$push":{
"hobbies":{"$each":["tea","dancing"]}
}})
# 按照位置且只能从开头或结尾删除元素:$pop
#1、{"$pop":{"key":1}} 从数组末尾删除一个元素
db.t1.update({"name":"c"},{"$pop":{
"hobbies":1}
})
#2、{"$pop":{"key":-1}} 从头部删除
db.t1.update({"name":"c"},{"$pop":{
"hobbies":-1}
})
# 按照条件删除元素
# "$pull" 把符合条件的统统删掉,而$pop只能从两端删
db.t1.update({"name":"c"},{"$pull":{
"hobbies":"read"}},{"multi":true}
重复值添加$addToSet
#避免添加重复:"$addToSet" # 如果重复就不再添加了
db.urls.insert({"_id":1,"urls":[]})
db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
db.urls.update({"_id":1},{
"$addToSet":{
"urls":{
"$each":[
'http://www.baidu.com',
'http://www.baidu.com',
'http://www.xxxx.com'
]
}
}
}
)