当前位置:网站首页>MongoDB文档存储
MongoDB文档存储
2022-08-02 03:08:00 【W_chuanqi】
个人简介
作者简介:大家好,我是W_chuanqi,一个编程爱好者
个人主页:W_chaunqi
支持我:点赞+收藏️+留言
愿你我共勉:“若身在泥潭,心也在泥潭,则满眼望去均是泥潭;若身在泥潭,而心系鲲鹏,则能见九万里天地。”
MongoDB 文档存储
NoSQL,全称为 Not Only SQL,意为不仅仅是 SQL,泛指非关系型数据库。NoSQL 是基于键值对的,而且不需要经过 SQL层的解析,数据之间没有耦合性,性能非常高。
非关系型数据库又可细分如下。
- 键值存储数据库:代表有 Redis、Voldemort 和 Oracle BDB 等。
- 列存储数据库:代表有 Cassandra、HBase 和 Riak 等。
- 文档型数据库:代表有 CouchDB 和 MongoDB 等。
- 图形数据库:代表有 Neo4J、InfoGrid 和 Infinite Graph 等。
对于爬虫的数据存储来说,一条数据可能存在因某些字段提取失败而缺失的情况,而且数据可能随时调整。另外,数据之间还存在嵌套关系。如果使用关系型数据库存储这些数据,一是需要提前建表,二是如果数据存在嵌套关系,还需要进行序列化操作才可以存储,这非常不方便。如果使用非关系型数据库,就可以避免这些麻烦,更简单、高效。
本节中,我们主要介绍 MongoDB 存储操作。
MongoDB 是由 C++语言编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容的存储形式类似JSON 对象。它的字段值可以包含其他文档、数组及文档数组,非常灵活。本节我们就来看看 Python 3 下 MongoDB 的存储操作。
1.准备工作
在开始之前,请确保已经安装好了 MongoDB 并启动了其服务,安装方式可以参考:
http://www.runoob.com/mongodb/mongodb-tutorial.html
除了安装好 MongoDB 数据库,我们还需要安装好 Python 的 PyMongo 库,如尚未安装,可以很用 pip 来安装:
pip install pymongo
安装完成
安装好 MongoDB 数据库和 PyMongo 库之后,我们便可以开始本节的学习了。
2.连接 MongoDB
连接 MongoDB时,需要使用 PyMongo库里面的 MongoClient方法,一般而言,传人MongoDB的IP 及端口即可。MongoClient 方法的第一个参数为地址 host,第二个参数为端口 port(如果不传入此参数,默认取值为 27017):
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
这样就可以创建 MongoDB 的连接对象了。
另外,还可以直接给 MongoCLient 的第一个参数 host 传人 MongoDB 的连接字符串,它以mongdb开头,例如:
client = MongoClient('mongodb://localhost:27017/')
这可以达到同样的连接效果。
3.指定数据库
在MongoDB 中、可以建立多个数据库,所以我们需要指定操作哪个数据库。这里我们以指定 test 数据库为例来说明:
db = client.test
这里调用 client 的 test 属性即可返回test数据库。当然,也可以这样指定:
db = client['test']
这两种方式是等价的。
4.指定集合
MongoDB 的每个数据库又都包含许多集合(collection ),这些集合类似于关系型数据库中的表。
下一步需要指定要操作哪些集合,这里指定一个集合,名称为 students。与指定数据库类似,指定集合也有两种方式:
collection = db.students
//或
collection = db['students']
这样我们便声明了一个集合对象。
5.插入数据
接下来,便可以插人数据了。在 students 这个集合中,新建一条学生数据,这条数据以字典形式表示:
student = {
'id': '20170101',
'name': 'Jordan',
'age': 20,
'gender': 'male'
}
这里指定了学生的学号、姓名、年龄和性别。然后直接调用 collection 类的 insert_one 方法(插入一条数据)即可插人数据,代码如下:
result = collection.insert_one(student)
print(result)
print(result.inserted_id)
在 MongoDB 中,每条数据都有一个_id 属性作为唯一标识。如果没有显式指明该属性,那么MongoDB 会自动产生一个 Objectid 类型的_id 属性,insert_one 方法会返回 InsertOneResult对象,我们可以调用inserted_id属性获取_id。
运行结果如下:
当然,也可以同时插人多条数据,这里我们使用insert_many方法,数据只需要以列表形式传递即可,实例如下:
student1 = {
'id': '20170101',
'name': 'Jordan',
'age': 20,
'gender': 'male'
}
student2 = {
'id': '20170102',
'name': 'Mike',
'age': 21,
'gender': 'male'
}
result = collection.insert_many([student1, student2])
print(result)
print(result.inserted_ids)
运行结果如下:
该方法返回的是 InsertManyResult 类型的对象,调用inserted_ids属性可以获取插入数据的_id列表。
6.查询
插人数据后,我们可以利用 find_one 或 find 方法进行查询,用前者查询得到的是单个结果,后者则会返回一个生成器对象。实例代码如下:
result = collection.find_one({
'name': 'Mike'})
print(type(result))
print(result)
这里我们查询 name 值为 Mike 的数据,运行结果如下:
可以发现,结果是字典类型,它多了_id 属性,这就是 MongoDB 在插人数据过程中自动添加的。
此外,我们也可以根据 ObjectId 来查询数据,此时需要使用 bson 库里面的 objectid:
from bson.objectid import ObjectId
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db.students
result = collection.find_one({
'_id': ObjectId('62e4ff121fc967ff629bf0db')})
print(result)
其查询结果依然是字典类型,具体如下:
当然,如果查询结果不存在,则会返回 None。
若要查询多条数据,可以使用 find 方法。例如,查找 age 为 20 的数据,实例代码如下:
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db.students
result = collection.find({
'age': 20})
print(result)
for item in result:
print(item)
运行结果如下:
返回结果是 Cursor 类型,相当于一个生成器,通过遍历能够获取所有的结果,其中每个结果都是字典类型。
如果要查询 age 大于 20 的数据,则写法如下:
result = collection.find({
'age': {
'$gt': 20}})
这里的查询条件中的键值已经不是单纯的数字了,而是一个字典,其键名为比较符号$gt,意思是大于;键值为20。
下表将比较符号进行了归纳。
符号 | 含义 | 实例 |
---|---|---|
$lt | 小于 | {‘age’: {‘$lt’: 20}} |
$gt | 大于 | {‘age’: {‘$gt’: 20}} |
$lte | 小于等于 | {‘age’: {‘$lte’: 20}} |
$gte | 大于等于 | {‘age’: {‘$gte’: 20}} |
$ne | 不等于 | {‘age’: {‘$ne’: 20}} |
$in | 在范围内 | {‘age’: {‘$in’: 20}} |
$nin | 不在范围内 | {‘age’: {‘$nin’: 20}} |
另外,还可以进行正则匹配查询。例如,执行以下代码查询 name 以M为开头的学生数据:
results=collection.find({
'name':{
'$regex':'^M.*'}})
这里使用$regex 来指定正则匹配,^M.*代表以M为开头的正则表达式。
下面将一些功能符号归类为下表 。
符号 | 含义 | 实例 | 实例含义 |
---|---|---|---|
$regex | 匹配正则表达式 | {‘name’:{‘$regex’:‘^M.*’}} | name 以M为开头 |
$exists | 属性是否存在 | {‘name’:{‘$exists’: True)} | 存在 name 属性 |
$type | 类型判断 | {‘age’:{‘$type’:‘int’}} | age 的类型为 int |
$mod | 数字模操作 | {‘age’:{‘$mod’:[5, 0]}} | age模5余0 |
$text | 文本查询 | {‘KaTeX parse error: Expected '}', got 'EOF' at end of input: text':{'search’:'Mike"}} | text 类型的属性中包含Mike 字符串 |
$where | 高级条件查询 | {‘$where’:‘obj.fans_count == obj.follows_count’} | 自身粉丝数等于关注数 |
7.计数
要统计查询结果包含多少条数据,可以调用 estimated_document_count() 方法。例如统计所有数据条数,代码如下:
count = collection.estimated_document_count()
print(count)
统计符合某个条件的数据有多少条,这里需要调用count_documents()方法,代码如下:
count = collection.count_documents({
'age': 20})
print(count)
运行结果是一个数值,即符合条件的数据条数。
注意
estimated_document_count() 和count_documents()使用时要注意区分。。。
8.排序
排序时,直接调用 sort 方法,并传入排序的字段及升降序标志即可。实例代码如下:
results = collection.find().sort('name', pymongo.ASCENDING)
print([result['name'] for result in results])
运行结果如下:
这里我们调用 pymongo.ASCENDING 指定按升序排序。如果要降序排,可以传入 pymongo.DESCENDING。
9.偏移
在某些情况下,我们可能只想取某几个元素,这时可以利用skip方法偏移几个位置,例如偏移2,即忽略前两个元素,获取第三个及以后的元素:
results = collection.find().sort('name', pymongo.ASCENDING).skip(2)
print([result['name'] for result in results])
运行结果如下:
另外,还可以使用 1imit 方法指定要获取的结果个数,实例代码如下:
results = collection.find().sort('name', pymongo.ASCENDING).skip(2).limit(2)
print([result['name'] for result in results])
运行结果如下:
如果不使用 limit 方法加以限制,原本会返回三个结果,而加了限制后,会截取两个结果并返回。
值得注意的是,在数据库中数据量非常庞大的时候(例如千万、亿级别),最好不要使用大偏移量来查询数据,因为这样很可能导致内存溢出。此时可以使用类似如下操作来查询:
from bson.objectid import ObjectId
collection.find({
'_id': {
'$gt': ObjectId('62e5fe905de9ec6ebbe04dc6')}})
这里需要记录好上次查询的_id。
10.更新
对于数据更新,我们可以使用单独的 update_one 方法和update_many 方法来处理单条和多条数据更新过程,用法比较严格,第二个参数都需要使用 $ 类型操作符作为字典的键名,实例代码如下:
condition = {
'name': 'Kevin'}
student = collection.find_one(condition)
student['age'] = 25
result = collection.update_one(condition, {
'$set': student})
print(result)
print(result.matched_count, result.modified_count)
这里调用的是 update_one 方法,其第二个参数需要使用{‘$set’:student}这种形式的数据。然后分别调用 matched_count 和 modified_count 属性,可以获得匹配的数据条数和影响的数据条数。
运行结果如下:
可以发现 update_one 方法的返回结果是 UpdateResult 类型。我们再看一个例子:
condition = {
'age': {
'$gt': 20}}
result = collection.update_one(condition, {
'$inc': {
'age': 1}})
print(result)
print(result.matched_count, result.modified_count)
这里指定查询条件为 age 大于 20,然后更新条件是{‘$inc’:{‘age’:1}},也就是对 age 加1,因此执行 update_one 方法之后,会对第一条符合查询条件的学生数据的 age 加 1。
运行结果如下:
可以看到匹配条数为1条,影响条数也为1条。
但如果调用 update_many 方法,则会更新所有符合条件的数据,实例代码如下:
condition = {
'age': {
'$gt': 20}}
result = collection.update_many(condition, {
'$inc': {
'age': 1}})
print(result)
print(result.matched_count, result.modified_count)
运行结果如下:
可以看到,这时匹配条数就不再为1条了,所有匹配到的数据都会被更新。
11.删除
这里存在两个新的官方推荐方法——delete_one 和 delete_many。delete_one 即删除第一条符合条件的数据,delete_many 即删除所有符合条件的数据。实例代码如下:
result = collection.delete_one({
'name': 'Kevin'})
print(result)
print(result.deleted_count)
result = collection.delete_many({
'age': {
'$lt': 25}})
print(result.deleted_count)
运行前:
运行后:
两个方法的返回结果都是 DeleteResult类型,可以调用 deleted_count 属性获取删除的数据条数。
12.其他操作
除了以上操作,PyMongo还提供了一些组合方法,例如 find_one_and_delete、find_one_and_replace和find_one_and_update,分别是查找后删除、替换和更新操作,用法与上述方法基本一致。
另外,还可以对索引进行操作,相关方法有 create_index、create_indexes 和 drop_index等。
边栏推荐
猜你喜欢
Navicat cannot connect to database Mysql because of WiFi
MySQL8--Windows下使用压缩包安装的方法
Go语学习笔记 - gorm使用 - 表增删改查 Web框架Gin(八)
【遥控器开发基础教程3】疯壳·开源编队无人机-ADC(摇杆控制)
小程序(开发必备常识)1
I will give you a chance to interview in a big factory. Can you interview?Come in and see!
Heao Technology Network Interview (with reference answers)
Brute force visitors
精益思想如何加速企业的全局价值流动?
Keil开发环境安装教程
随机推荐
Day34 LeetCode
基于可逆网络的单一图像超分辨率
Go简单实现协程池
Brute force visitors
CentOS7安装Oracle数据库的全流程
MySQL修改最大连接数限制
ModuleNotFoundError: No module named ‘openpyxl‘
关于#sql#的问题:该怎么写sql语句,
py0_二十一天计划书
DVWA安装教程(懂你的不懂·详细)
PHP WebShell 免杀
面试必备!TCP协议经典十五连问!
PHP WebShell Free Kill
IPIDEA的使用方式
Redis主从、哨兵、 Cluster集群一锅端!
Lua安装及常用命令使用
JDBC--Druid数据库连接池以及Template基本用法
分布式事务解决方案模型
给你一个大厂面试的机会,你能面试上吗?进来看看!
Go语学习笔记 - gorm使用 - gorm处理错误 Web框架Gin(十)