MongoDB
MongoDB是一个高性能、开源、无模式的文档类型数据库。
MongoDB的性能
- 对数据库高并发请求
- 对海量数据的高效率存储和访问需求
- 对数据库的高可扩展性
NoSQL特点
- 可以处理超大量的数据
- 可以运行在PC服务器集群上PC
MongoDB的特点
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库中功能最丰富、最像关系型数据库的。它支持的数据结构是比较松散的,是类似json的bjson格式,因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象查询语句,可以实现类似关系数据库单表查询的绝大部分功能,而且还支持数据建立索引。它是一个面向集合的,模式自由的文档型数据库
面向集合(Collection-Oriented)
数据被分组存储在数据集中,被称为一个集合(Collection)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库里的表(table),不同的是它不需要定义任何模式(schema)
模式自由(Schema-free)
对于存储在MongoDB数据库中的文件,我们不需要知道它的任何结构定义,例如以下两个记录可以放在同一个集合里,即在关系数据库里,一个表有(name,age),那么所有创建的对象就有这两个属性,但是mongoDB中不需要。
{"Welcome":"Beijing"}
{"age":20}
文档型
我们存储的数据是键-值对的集合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档,我们把这个格式叫做BSON(Binary Serialized document Notation)
适用场景
- 网站数据:MongoDB非常适合实时的插入,更新和查询,并具备网站实时数据存储所需的复制及高度伸缩性
- 缓存:由于性能高,MongoDB也适合作为信息基础设施的缓存层,在系统重启之后,由MongoDB搭建的持久化缓存层可以避免下层的数据源过载
- 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据可能会比较昂贵,这时就可以采用MongoDB
- 高伸缩性场景:MongoDB非常适合由数十或数百台服务器组成的数据库
- 用于对象及JSON数据的存储:MongoDB的BSON数据格式非常适合文档化格式的存储及查询
MongoDB安装
- 可以自行官网下载安装包
- 配置环境变量
- 找到mongoDB安装路径,进入到bin目录下,保存此文件路径,如: C:\Users\mongoDB\bin
- 右键点击此电脑->属性->高级系统设置->高级->环境变量->编辑用户的变量path->将上面的路径添加进去
- 在安装MomgoDB文件夹的根目录新建一个文件夹data,在data中新建一个文件夹db,进入到mongoDB/bin的目录下,执行以下命令:
mongod --dbpath E:\ data\ db
- 启动mongoDB,此窗口为mongoDB服务器,cmd输入: mongod (出现waiting for connecting port xx即表示成功开启服务)
- 重新开启一个cmd窗口,此窗口为mongoDB客户端,cmd输入:mongo 进行连接,当此窗口出现”>”,进行简单操作验证是否成功
图形化界面操作
可以使用robo3/mongoDB Compass图形界面
MongoDB的操作
MongoDB与SQL的概念对比
SQL | MongoDB |
---|---|
database | database |
table | collection |
row | document or BSON document |
column | field |
index | index |
primary key | _id(auto set) |
数据类型
以下是几种MongoDB常用的数据类型:
类型 | 名称 |
---|---|
Object ID | 文档ID |
String | 字符串,最常用,必须是有效的UTF-8 |
Boolean | 存储一个布尔值,true/false |
Integer | 整数可以是32位或64位,这取决于服务器 |
Double | 存储浮点值 |
Arrays | 数组或列表,多个值存储在一个键 |
Object | 用于嵌入式文档,即一个值为一个文档 |
Null | 存储Null的值 |
Timestamp | 时间戳 |
Date | 存储当前日期或时间的UNIX时间格式 |
Object ID
- 每个文档都有一个属性,为_id,保证每个文档的唯一性
- 可以自己设置_id插入文档
- 如果没有提供,MongoDB默认为每个文档提供里一个独特的_id,类型为objectID
- objectID是一个12字节的16进制数:
- 前4个字节为时间戳
- 接下来3个字节的机器ID
- 接下来的2个字节中MongoDB的服务进程id
- 最后3个字节是简单的增量值
collection与table的差异】
table
id | title | content |
---|---|---|
1 | 天气 | 万里无云 |
2 | 心情 | 哈哈 |
特点:
- 有结构
- 行遵循结构
collection
{id:1,title:'万里无云'}
{id:2,title:'哈哈',date:'2020'}
特点:
- collection无结构
- 文档相互独立,没有固定的结构
数据库操作
show dbs #查看已有数据库
use dataName #选择数据库,如果没有此数据库则新建一个名字为dataName的数据库
use person
show collection #查看已有的集合
db.createCollection("集合名") #创建集合
db.createCollection("student")
db.集合名.drop() #删除表 ,先切换到该数据库才能进行删除
db.dropDatabase() #删除当前数据库
注:如果我们对新创建的数据库没有进行操作,该数据库只是在内存中暂时存放,只有对该数据库进行实际操作后,数据库才会存放在硬盘里
MongoDB数据的基本操作
数据的增加
插入文档时,如果不指定_id参数,MongoDB会为文档分配一个唯一的ObjectID
insert
insert可以一次性插入一个文档,而不用遍历,效率高。insert中只要两个文档id相同就无法进行插入
db.集合名.insert(document)
save
在save方法里,如果不存在重复的对象,则向collection里插入数据,如果已经存在,save会调用update更新集合里的记录。save需要遍历列表,一个个插入,效率较低。save更新相同的id的内容
db.集合名.save(document)
例子
数据库student中有一个{ _ id:”1”,”name”:”zby”}的文档
db.student.insert({"_id":"1","name":"ybz"}) #会报错,主键重复
db.student.save({"_id":"1","name":"ybz"}) #数据库的文档替换成{_id:"1","name":ybz}
插入多个文档
使用列表插入
db.student.insert([{"name":"zby"},{"name":"ybz"},{"name":"by"}])
效果如图所示:
数据的修改
语法:
db.集合名.update(<query>,<update>,<multi:boolean>)
- 参数query: 查询条件,类似sql语句update中的where部分
- 参数update: 更新操作符,类似sql语句update中的set部分
- 参数multi:可选,默认false,表示只更新找到第一条记录,值为true标识把满足条件的所有文档全部更新
例子
db.student.update({"name":"by"},{"age":18}) #将第一条name为by的文档中的age改为18,并且会改变文档结构,即如果没有age会将name改为age来存储
db.student.update({"name":"by"},{$set:{"age":18}) #只更新数据,不更新文档结构
db.student.update({"name":"by"},{$set:{"age":18},{"multi":true}) #更新所有匹配到的数据
原集合:
执行
db.student.update({"name":"bob","age":19})
继续执行
db.student.update({"age":19},{$set:{"name":"bob"})
最后执行
db.student.insert({"name":"bob","age":35}) db.student.update({"name":"bob"},{$set:{"age":20},{"multi":true})
简单查询
find
查找到所有匹配数据
db.集合名.find({条件文档})
findOne
只返回匹配的第一个数据
db.集合名.findOne({条件文档})
运算符
语法 | 操作 | 格式 |
---|---|---|
$eq | 等于 | { |
$lt | 小于 | { |
$lte | 小于或等于 | { |
$gt | 大于 | { |
$gte | 大于或等于 | { |
$ne | 不等于 | { |
$or | 或 | {$or:[{},{}]} |
$in | 在范围内 | {age:{$in:[value1,value2]}} |
$nin | 不在范围内 | {age:{$nin:[value1,value2]}} |
删除文档
db.student.remove({"name":"bob"}) #删除name=bob的文档
db.student.remove({}) #删除集合里所有文档
例子
db.student.find({"age":{$gt:16}})
db.student.find({$or:[{"age":{$gte:18}},{"name":"bob"}]})
其他操作
模糊匹配
使用//或$regex编写正则表达式
db.student.find({"name":/^bob/})
db.student.find({"name":{$regex:'^bob'}})
limit
用于读取指定数量的文档
db.集合名.find().limit(number)
skip
用于跳过指定数量的文档
db.集合名.find().skip(number)
sort
用于对结果集合进行排序
db.集合名.find().sort({字段1,字段2})
- 参数1为升序排序
- 参数-1为降序排序
Python与MongoDB交互
安装环境
在Anaconda Prompt中使用pip安装(直接使用pycharm解释器搜索安装)
pip install pymongo
使用样例
在连接之前要确保mongoDB服务器已经打开
引入包pymongo
import pymongo
连接/创建客户端
下面是两种连接客户端的方法client = pymongo.MongoClient("localhost",27017) #也可以不传参,默认为本机mongoDB服务器 client = pymongo.MongoClient("mongodb://localhost:27017")
获得数据库person
下面是两种获取数据库的方式db = client.person db = client['person']
获得集合student
下面是两种获取集合的方式collection = person.student collection = person['student']
添加文档
data = {"name":"bai","age":19} data2 = {"name":"yang","age":12} student.insert_one(data1) #插入一个文档 student.insert_many([data1,data2]) #插入多个文档
查找文档
target = student.find_one({"name":"bai"}) target = student.find({"name":"bai"})
获取文档
result = student.next() #一个文档一个文档的取出
删除文档
student.remove(data1) #以文档对象的形式删除 student.remove({"name":"bai"}) #以field筛选删除
打印文档
target1 = student.find_one({"name":"bai"}) #返回一个文档直接打印 print(target1) target2 = list(student.find({"name":"bai"})) #返回多个文档使用list()函数或循环
爬虫爬取信息存放到mongoDB里
创建一个爬虫(见爬虫篇),
spider.py
- 先爬取网页,提取要存储进MongoDB的数据
- 将提取到数据使用zip进行打包
def parse(self, response): download_urls = response.xpath("//div[@class='cont']/ul//a[@class='btn-b']/@href").extract() # 获取整页下载链接用getall() names = response.xpath("//div[@class='cont']//em//text()").extract() update_times = response.xpath("//div[@class='cont']//span[@class='ml10']//text()").extract() #将上面抓取到的元素打包成元组 for download_url,name,update_time in zip(download_urls,names,update_times): yield { "name":name, "download_url":download_url, "update_time":update_time, }
pipelines.py
- 连接mongoDB
- 向对应的集合中插入文档
- 关闭mongoDB连接
import pymongo class MongodbPipeline(object): #连接MongoDB def open_spider(self,spider): self.client = pymongo.MongoClient() def process_item(self, item, spider): self.client.s2345.softInfo.insert_one(item) return item #关闭MongoDB def close_spider(self,spider): self.client.close()
settings.py
改robots/item_pipelines/user-agent
ITEM_PIPELINES = {
'xx.pipelines.MongodbPipeline': 300,
}