第78天: Python 操作 MongoDB 數據庫介紹


by 極光

MongoDB 是一款面向文檔型的 NoSQL 數據庫,是一個基於分布式文件存儲的開源的非關系型數據庫系統,其內容是以 K/V 形式存儲,結構不固定,它的字段值可以包含其他文檔、數組和文檔數組等。其采用的 BSON(二進制 JSON )的數據結構,可以提高存儲和掃描效率,但空間開銷會有些大。今天就為大家簡單介紹下在 Python 中使用 MongoDB 。

安裝 PyMongo 庫

在 Python 中操作 MongoDB ,需要使用 PyMongo 庫,執行如下命令安裝:

pip3 install pymongo

連接 MongoDB 數據庫

連接時需要使用 PyMongo 庫里面的 MongoClient 模塊,有兩種方式可以創建連接,默認只需要傳入IP和端口號即可。如果數據庫存在賬號密碼,則需要指定連接的數據庫,並進行鑒權才能連接成功。

#導入 MongoClient 模塊
from pymongo import MongoClient, ASCENDING, DESCENDING

# 兩種方式
#1. 傳入數據庫IP和端口號
mc = MongoClient('127.0.0.1', 27017)

#2. 直接傳入連接字串
mc = MongoClient('mongodb://127.0.0.1:27017')

# 有密碼的連接
# 首先指定連接testdb數據庫
db = mc.testdb

# 通過authenticate方法認證賬號密碼
db.authenticate('username','password')

# 檢查是否連接成功,輸出以下結果表示連接成功
print(mc.server_info())
# {'version': '4.2.1', 'gitVersion': 'edf6d45851c0b9ee15548f0f847df141764a317e', 'modules': [], 'allocator': 'tcmalloc', 'javascriptEngine': 'mozjs', 'sysInfo': 'deprecated', 'versionArray': [4, 2, 1, 0], 'openssl': {'running': 'OpenSSL 1.1.1  11 Sep 2018', 'compiled': 'OpenSSL 1.1.1  11 Sep 2018'},  ……省略 ,  'ok': 1.0}

MongoDB 數據庫操作

成功連接數據庫,接下來我們開始介紹通過 MongoClient 模塊如何對 mongoDB 數據庫進行 CURD 的操作。

獲取數據庫和集合

首先要指定需要操作的數據庫和集合,這里的數據庫可以對應為 MysqlDataBase,集合對應為 MysqlTable。需要注意的是在 mongoDB 中,不需要提前創建數據庫和集合,在你操作它們時如果沒有則會自動創建,但都是延時創建的,在添加 Document 時才會真正創建。

# 指定操作數據庫的兩種方式
#1. 獲取 testdb 數據庫,沒有則自動創建
db = mc.testdb

#2. 效果與上面 db = mc.testdb 相同
db = mc['testdb']

# 打印出testdb數據庫下所有集合(表)
print(db.collection_names())


# 指定操作集合的兩種方式
#1. 獲取 test 集合,沒有則自動創建
collection = db.test

#2. 效果與 collection = db.test 相同
collection = db['test']

# 打印集合中一行數據
print(collection.find_one())

數據的插入操作

在 MongoDB 中,每條數據其實都有一個 _id 屬性作為唯一標識。如果沒有顯式指明該屬性,MongoDB 會自動產生一個 ObjectId 類型的 _id 屬性,insert() 方法會在執行后返回 _id 值。不過在 PyMongo 3.x 版本中,官方已經不推薦使用 insert() 方法,而是推薦使用insert_one()insert_many() 方法來分別插入單條記錄和多條記錄。

# 要插入到集合中的對象
book = {
      'name' : 'Python基礎',
      'author' : '張三',
      'page' : 80
}

# 向集合中插入一條記錄
collection.insert_one(book)
# 返回結果:{'_id': ObjectId('5de4c7b90ae08431839ac2a7'), 'name': 'Python基礎', 'author': '張三', 'page': 80}

# 對於insert_many()方法,我們可以將數據以列表形式傳遞參數
book1 = {
      'name' : 'Java基礎',
      'author' : '李白',
      'page' : 100
}
book2 = {
      'name' : 'Java虛擬機',
      'author' : '王五',
      'page' : 100
}

# 創建 book_list 列表
book_list = [book1, book2]

# 向集合中插入多條記錄
collection.insert_many(book_list)
# 返回結果: <pymongo.results.InsertManyResult object at 0x7f80a39fa408>

數據的查詢操作

查詢需要使用 find_one()find() 方法,其中 find_one() 查詢得到的是單個結果,即一條記錄,find() 則返回一個生成器對象。下面我們就來查詢上面剛插入的數據,如果查詢不到數據則返回 None ,代碼如下:

# 通過條件查詢一條記錄,如果不存在則返回None
res = collection.find_one({'author': '張三'})
print (res)
# 打印結果:{'_id': ObjectId('5de4c7b90ae08431839ac2a7'), 'name': 'Python基礎', 'author': '張三', 'page': 80}

# 通過條件查詢多條記錄,如果不存在則返回None
res = collection.find({'page': 100})
print (res)
#打印結果:<pymongo.cursor.Cursor object at 0x7f80a39daa58>

# 使用 find() 查詢會返回一個對象
# 遍歷對象,並打印查詢結果
for r in res:
   print(r)
#打印結果:
# {'_id': ObjectId('5de4c8ae0ae08431839ac2a8'), 'name': 'Java基礎', 'author': '李白', 'page': 100}
# {'_id': ObjectId('5de4c8ae0ae08431839ac2a9'), 'name': 'Java虛擬機', 'author': '王五', 'page': 100}

# 查詢page大於50的記錄
res = collection.find({'page': {'$gt': 50}})
# 通過遍歷返回對象,結果如下:
# {'_id': ObjectId('5de4c7b90ae08431839ac2a7'), 'name': 'Python基礎', 'author': '張三', 'page': 80}
# {'_id': ObjectId('5de4c8ae0ae08431839ac2a8'), 'name': 'Java基礎', 'author': '李白', 'page': 100}
# {'_id': ObjectId('5de4c8ae0ae08431839ac2a9'), 'name': 'Java虛擬機', 'author': '王五', 'page': 100}

上面查詢條件中我們用到了 $gt 的比較運算符,關於查詢條件中的比較運算符和功能運算符對照表如下:

符號 含義 舉例
$gt 大於 {'page': {'$gt': 50}
$lt 小於
$lte 小於等於
$gte 大於等於
$ne 不等於
$in 在范圍內 {'page': {'$in': [50, 100]}}
$nin 不在范圍內 {'page': {'$nin': [50, 100]}}
$regex 匹配正則表達式 {'name': {'$regex': '^張.*'}}
$exists 屬性是否存在 {'name': {'$exists': True}}
$type 類型判斷 {'name': {'$type': 'string'}}
$mod 數字模操作 {'page': {'$mod': [80, 10]}}
$text 文本查詢 {'$text': {'$search': 'Java'}}
$where 高級條件查詢 {'$where': 'obj. author == obj. full_name'}

數據的更新操作

更新操作和插入操作類似,PyMongo 提供了兩種更新方法,即 update_one()update_many() 方法,其中 update_one() 方法只會更新滿足條件的第一條記錄。

注意:

  • 如果使用 $set,則只更新 book 對象內存在的字段,如果更新前還有其他字段,則不更新也不刪除。
  • 如果不使用 $set,則會把更新前的數據全部用 book 對象替換,如果原本存在其他字段則會被刪除。
# 查詢一條記錄
book = collection.find_one({'author': '張三'})
book['page'] = 90

# 更新滿足條件{'author', '張三'}的第一條記錄
res = collection.update_one({'author': '張三'}, {'$set': book})

# 更新返回結果是一個對象,我們可以調用matched_count和modified_count屬性分別獲得匹配的數據條數和影響的數據條數。
print(res.matched_count, res.modified_count)
#打印結果:1 1

# 更新滿足條件 page>90 的所有記錄,page 字段自加 10
res = collection.update_many({'page': {'$gt': 90}}, {'$inc': {'page': 10}})

# 打印更新匹配和影響的記錄數
print(res.matched_count, res.modified_count)
#打印結果:2 2

book3 = {'name':'Python高級', 'author':'趙飛', 'page': 50}

#upsert=True表示如果沒有滿足更新條件的記錄,則會將book3插入集合中
res = collection.update_one({'author': '趙飛'}, {'$set': book3}, upsert=True)
print(res.matched_count, res.modified_count)
#打印結果:0 0

# 查詢所有記錄,並遍歷打印出來
res = collection.find()
for r in res:
   print(r)
#打印結果:
# {'_id': ObjectId('5de4c7b90ae08431839ac2a7'), 'name': 'Python基礎', 'author': '張三', 'page': 90}
# {'_id': ObjectId('5de4c8ae0ae08431839ac2a8'), 'name': 'Java基礎', 'author': '李白', 'page': 110}
# {'_id': ObjectId('5de4c8ae0ae08431839ac2a9'), 'name': 'Java虛擬機', 'author': '王五', 'page': 110}
# {'_id': ObjectId('5de4d76f71aa089d58170a92'), 'author': '趙飛', 'name': 'Python高級', 'page': 50}

集合的刪除操作

刪除數據同樣推薦使用兩個方法 delete_one()delete_many() ,其中 delete_one() 為刪除第一條符合條件的記錄。具體操作代碼如下:

# 刪除滿足條件的第一條記錄
result = collection.delete_one({'author': '張三'})
# 同樣可以通過返回對象的 deleted_count 屬性查詢刪除的記錄數
print(result.deleted_count)
# 打印結果:1

# 刪除滿足條件的所有記錄,以下為刪除 page < 90 的記錄
result = collection.delete_many({'page': {'$lt': 90}})
print(result.deleted_count)
# 打印結果:1

其他數據庫操作

除了以上標准的數據庫操作外,PyMongo 還提供了以下通用且方便的操作方法,比如 limit() 方法用來讀取指定數量的數據
skip() 方法用來跳過指定數量的數據等,具體請看如下代碼:

# 查詢返回滿足條件的記錄然后刪除
result = collection.find_one_and_delete({'author': '王五'})  
print(result)
# 打印結果:{'_id': ObjectId('5de4c8ae0ae08431839ac2a9'), 'name': 'Java虛擬機', 'author': '王五', 'page': 110}

# 統計查詢結果個數
# 全部結果個數
collection.find().count()
# 返回結果:1

# 滿足條件結果個數
collection.find({'page': 100}).count()
# 返回結果:0

# 查詢結果按字段排序
# 升序
results = collection.find().sort('page', ASCENDING)

# 降序
results = collection.find().sort('page', DESCENDING)

# 下面查詢結果是按page升序排序,只返回第二條記錄及以后的兩條結果
results = collection.find().sort('page', ASCENDING).skip(1).limit(2)
print(results)

注意:在數據量在在千萬、億級別龐大的時候,查詢時最好 skip() 的值不要太大,這樣很可能導致內存溢出。

數據索引操作

默認情況下,數據插入時已經有一個 _id 索引了,當然我們還可以創建自定義索引。

# unique=True時,創建一個唯一索引,索引字段插入相同值時會自動報錯,默認為False
collection.create_index('page', unique= True)
# 打印結果:'page_1'

# 打印出已創建的索引
print(collection.index_information())
# 返回結果:{'_id_': {'v': 2, 'key': [('_id', 1)], 'ns': 'testdb.test'}, 'page_1': {'v': 2, 'unique': True, 'key': [('page', 1)], 'ns': 'testdb.test'}}

# 刪除索引
collection.drop_index('page_1')

#刪除集合
collection.drop()

總結

本文為大家介紹了 Python 中如何創建連接 MongoDB 數據庫,並通過代碼的方式展示了對 MongoDB 數據的增刪改查以及排序索引等操作,通過以上學習個人感覺操作起來還是比較簡單方便的。今天就先介紹到這里,以后還會為大家介紹其他數據庫的操作。

參考

PyMongo 文檔:https://pymongo.readthedocs.io/en/stable/

示例代碼:https://github.com/JustDoPython/python-100-day

關注公眾號:python技術,回復"python"一起學習交流


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM