聊聊 Python 數據處理全家桶(MongoDB 篇)
本文轉載自微信公眾號「AirPython」,作者星安果。轉載本文請聯(lián)系AirPython公眾號。
1. 前言
MongoDB 是基于分布式存儲,由 C++ 編寫的開源的 NoSql 數據庫
MongoDB 的內容存儲類似 JSON 對象,數據結構包含 3 種
分別是:
數據庫 - Databases
對應關系型數據庫中的數據庫(Database)
集合 - Collection
對應關系型數據庫中的 Table 表(Table)
文檔 - Document
對應數據庫表中的一條數據(Row Data)
2. 準備
Python 操作 MongoDB,常見的兩種方式是:Pymongo、Mongoengine
其中
- Mongoengine:面相對象,針對文檔型數據庫的 ORM,直接繼承于 Document 文檔,對文檔進行增刪改查
- Pymongo:通過 JSON 和 MongoDB 進行通信,將 MongoDB 的數據映射成 Python 內置的數據類型
首先,我們通過 pip3 命令安裝依賴
- # 安裝依賴
- # pymongo
- pip3 install pymongo
- # mongoengine
- pip3 install mongoengine
下面分別對 Pymongo 和 Mongoengine 進行說明
3. PyMongo
首先,創(chuàng)建一個數據庫連接對象
創(chuàng)建數據庫連接對象有二種方式,分別是:多參數、字符串拼接
- import pymongo
- # 創(chuàng)建數據庫連接對象的兩種方式
- # 方式一:多參數
- self.client = pymongo.MongoClient(host='ip地址', port=27017, username="root", password="123456",
- authMechanism="SCRAM-SHA-1")
- # 方式二:拼接
- # self.client = pymongo.MongoClient('mongodb://root:123456@ip地址:27017/')
接著,通過數據庫連接對象指定要操作的數據庫和操作集合
比如:要操作數據庫 temp 中的 students 集合
- # 指定要操作的數據庫:temp
- self.db = self.client.temp
- # 指定要操作集合students
- self.collection_students = self.db.students
接著,我們來實現(xiàn)增刪改查操作
1、新增
新增包含:新增單條數據和多條數據
單條數據插入對應的方法是:
- insert_one(dict)
該方法的返回值類型為 InsertOneResult
通過 inserted_id 屬性,可以獲取插入數據的 _id 值
- temp_data = {
- "id": "1",
- "name": "xag",
- "age": 18
- }
- # 1、直接調用集合的insert_one()方法插入數據(插入一條數據)
- result = self.collection_students.insert_one(temp_data)
- # 返回值為InsertOneResult,通過inserted_id屬性獲取_id的值
- print(result.inserted_id)
多條數據插入對應的方法是:
- insert_many([dict1,dict2...])
該方法的返回值類型為 InsertManyResult
通過 inserted_ids 屬性,可以獲取插入數據的 _id 屬性值列表
- # 2、插入多條數據-insert_many()
- result = self.collection_students.insert_many([temp_data, temp_data2])
- # 返回值為InsertManyResult,通過inserted_ids屬性獲取插入數據的_id列表值
- print(result.inserted_ids)
2、查詢
使用 PyMongo 查詢 MongoDB 數據庫,常用方法如下:
- 通過某一個屬性鍵值對,去查詢一條記錄 - find_one()
- 通過 ObjectId 值去查詢某一條記錄 - find_one()
- 通過某一個屬性鍵值對,去查詢多條記錄 - find()
- 通過大于、小于、等于等條件去比較查詢
- 正則匹配查詢
前面 3 種查詢方式,由于比較簡單,直接給出實例:
- def manage_query(self):
- """查詢數據"""
- # 1、通過某個屬性鍵值對,去查詢一條記錄 find_one()
- # 返回值為字典類型
- # {'_id': ObjectId('5f5c437cfe49fa9a16664179'), 'id': '1', 'name': 'xag', 'age': 18}
- result = self.collection_students.find_one({"name": "xag"})
- print(result)
- # 2、通過ObjectId值去查詢某一條記錄
- result = self.collection_students.find_one({"_id": ObjectId('5f5c437cfe49fa9a16664179')})
- print(result)
- # 3.1 查詢多條記錄 find()
- # 返回值為一個游標(生成器),pymongo.cursor.Cursor
- result_lists = self.collection_students.find({"name":"xag"})
- print(result_lists)
- for item in result_lists:
- print(item)
條件比較查詢,包含:大于($gt)、大于等于($gte)、小于($lt)、小于等于($lte)、不等于($ne)、在范圍內($in)、不在范圍內($nin)
比如:查詢年齡大于 18 歲的數據
- # 3.2 條件比較查詢,包含大于($gt)、大于等于($gte)、小于($lt)、小于等于($lte)、不等于($ne)、在范圍內($in)、不在范圍內($nin)
- # 查詢年齡大于18歲的記錄
- result = self.collection_students.find({'age': {'$gt': 18}})
- for item in result:
- print(item)
正則匹配查詢,包含:
- $regex:匹配正則表達式
- $exists:屬性是否存在
- $type:數據類型判斷
- $mod:數據模操作
- $text:文本包含查詢
- $where:高級條件查詢
比如,查詢 name 值以 "xag" 開頭的數據
- # 正則匹配查詢
- results = self.collection_students.find({'name': {'$regex': '^xag.*'}})
- for item in results:
- print(item)
關于查詢更加復雜的功能可以參考:
https://docs.mongodb.com/manual/reference/operator/query/
3、更新
更新操作包含:更新一條記錄和更新多條記錄
其中,更新一條記錄對應的方法是:
- update_one(query,update_content)
參數包含:查詢的條件、要修改的內容
- # 1、修改一條記錄 update_one(query,update_data)
- # 方法中有兩個參數,分別是:查詢條件、要修改的內容
- # 查詢條件
- query_condition = {"name": "xag"}
- # 要修改的內容
- update_content = {"$set": {"name": "星安果"}}
- # 使用update_one() 方法進行更新一條記錄
- result = self.collection_students.update_one(query_condition, update_content)
通過返回的結果可以獲取查詢匹配的記錄個數及影響的記錄個數
- # matched_count:匹配的記錄個數
- # modified_count:影響的記錄個數
- print(result.matched_count, result.modified_count)
更新多條記錄對應的方法是:
- update_many(query,update_content)
方法中的參數、返回值與修改單條記錄類似
- # 2、修改多條記錄 update_many(query,update_data)
- # 查詢條件
- query_condition = {"name": {"$regex": "^星.*"}}
- # 要修改的內容
- update_content = {"$set": {"name": "xag"}}
- # 將文檔中name以星開頭的記錄都設置為xag
- result = self.collection_students.update_many(query_condition, update_content)
- print(result)
- print(result.matched_count, result.modified_count)
4、刪除
刪除同樣包含:刪除查詢到的第一條記錄、刪除查詢到的所有記錄
分別對應的方法是:delete_one(query)、delete_many(query)
另外,在返回結果中可以獲取到真實被刪除的數目
- def manage_remove(self):
- """
- 刪除操作
- :return:
- """
- # 1、刪除查詢到的第一條記錄 delete_one()
- # result = self.collection_students.delete_one({'name': "xag2"})
- # print(result)
- # 刪除的數目
- # print(result.deleted_count)
- # 2、刪除多條記錄 delete_many()
- result = self.collection_students.delete_many({'name': "xag"})
- print(result)
- # 刪除的數目
- print(result.deleted_count)
5、計數和排名
常用的方法包含:
- limit(num):限制返回的結果數量
- skip(num):忽略 num 個元素,從 num + 1 個元素開始查看
- count_documents():查看集合中所有的文檔數量,也可以根據條件去查詢滿足的文檔數量
- sort():升序或者降序
- def manage_count_and_sort(self):
- """
- 計數和排序
- :return:
- """
- # 1、限制返回的結果數量 - limit()
- # result = self.collection_students.find().limit(2)
- # for item in result:
- # print(item)
- # 2、偏移 skip()
- # 比如:忽略前面兩個元素,從第3個元素開始查看
- # result = self.collection_students.find().skip(2)
- # print([result['name'] for result in result])
- # 3.1 查詢出集合中所有的文檔數量 count_documents()
- # result = self.collection_students.count_documents({})
- # print(result)
- # 3.2 根據條件去查詢,然后判斷結果數目
- # query_regex = {'name': {'$regex': '^xag.*'}}
- # result = self.collection_students.count_documents(query_regex)
- # print(result)
- # 4、排序 sort()
- # pymongo.ASCENDING:升序,DESCENDING:降序
- result = self.collection_students.find().sort('name', pymongo.DESCENDING)
- print([result['name'] for result in result])
4. Mongoengine
在使用 Mongoengine 操作 MongoDB 之前,需要先定義一個 Document 的子類
該子類對應 MongoDB 中的文檔,內部加入的靜態(tài)變量(包含:類型、長度等)對應數據庫文檔中的數據
- from mongoengine import *
- # Document的子類,對應文檔對象
- class Student(Document):
- name = StringField(required=True, max_length=500)
- age = IntField(required=True, default=18)
- create_time = DateTimeField(default=datetime.now)
- # 配置元數據
- # 指定集合為student
- meta = {'collection': 'student', 'strict': False}
利用 Mongoengine 內置的 connect() 方法,連接指定的數據庫
- # 連接數據庫temp
- def __init__(self):
- # 連接數據庫
- # 數據庫名稱:temp
- # auth方式:SCRAM-SHA-1
- result = connect('temp', host='ip地址', port=27017,
- username='root', password='123456', authentication_source='admin',
- authentication_mechanism="SCRAM-SHA-1")
- print(result)
接著,我們來實現(xiàn)增刪改查操作
1、新增
使用 Mongoengine 新增一條記錄到數據庫非常方便
只需要實例化一個文檔對象,調用 save() 方法,即可以存儲一條記錄到數據庫當中
- def insert(self):
- """
- 插入數據
- :return:
- """
- person = Student(name='xag2', age=20)
- person.save()
2、查詢
常見的查詢操作包含:
- 查詢集合中的所有記錄
- 查詢第一條記錄
- 通過主鍵 _ID,來查詢數據
- 條件查詢
對應的代碼如下:
- def query(self):
- """
- 普通查詢
- :return:
- """
- # 1、查看集合中所有數據
- # students = Student.objects.all()
- # print([item['name'] for item in students])
- # 2、查詢第一條記錄
- # student = Student.objects.first()
- # print(student.name, student.age, student.create_time)
- # 3、通過主鍵_ID來查詢數據
- result = Student.objects.filter(pk="5f5c5b34f5b0c049707a1710").first()
- print(result.name, result.age, result.create_time)
- # 4、條件查詢
- # 查詢年齡在18-20歲的數據
- # __gte:大于等于;__lte:小于等于
- # 默認是升序,可以加一個:-,代表逆序
- # students = Student.objects(age__gte=18, age__lte=20).order_by('name')
- students = Student.objects(age__gte=18, age__lte=20).order_by('-name')
- # for item in students:
- # print(item.name, item.age, item.create_time)
值得一提的是,Mongoengine 提供了關鍵字 Q 來實現(xiàn)高級查詢
比如:查詢 name 字段值為 xag,年齡為 18 歲的數據
- def query_advance(self):
- """
- 高級查詢
- :return:
- """
- # 查看name為xag,age為18的記錄的第一條
- student = Student.objects(Q(name="xag") & Q(age=18)).first()
- print(student.name, student.age, student.create_time)
進階操作可以參考:
https://docs.mongoengine.org/guide/querying.html
3、更新
Mongoengine 提供了 filter() 和 update() 兩個方法,分別用于過濾待更新的數據,指定的更新內容
- def update(self):
- """
- 更新記錄
- :return:
- """
- # 1、修改所有記錄
- # 修改name為xag的年齡都減少1歲
- # 增加一歲:inc__age=1
- # 減少一歲:dec__age=1
- # Student.objects.filter(name="xag").update(dec__age=1)
- # Student.objects.filter(name="xag").update(inc__age=1)
- # name為xag,age小于18的的所有記錄,更新為age=23
- # __lt:小于
- # __lte:小于等于
- # __gt:大于
- # __gte:大于等于
- # Student.objects.filter(name="xag", age__lt=18).update(age=23)
- # Student.objects.filter(age__lte=20).update(age=23)
如果只需要更改查詢到的第一條記錄,可以使用 update_one() 方法
- # 2、修改一條記錄
- # 年齡減少5歲
- Student.objects.filter(name='xag').update_one(dec__age=5)
4、刪除
刪除操作對應 delete() 方法
同樣,可以利用 filter() 和 first() 方法限制要刪除的范圍
- def delete(self):
- """
- 刪除數據
- :return:
- """
- # 1、刪除查詢到的第一條記錄
- # Student.objects.filter(name="xag").first().delete()
- # 2、刪除多條記錄
- # Student.objects.filter(name="xag").delete()
- # 刪除name值以xag開頭的所有記錄
- Student.objects.filter(name__startswith="xag").delete()
5.最后
本篇文章講解了 Python 操作 MongoDB,最常用的兩種使用方式