Python3 操作 MongoDB

一、安裝

pip3 install pymongo

二、基本使用

1. 導(dǎo)入模塊

import pymongo

2. 建立本地鏈接

cl = pymongo.MongoClient('localhost', 27017)

# 或者

cl = Mongocl('mongodb://localhost:27017/')

3. 獲取數(shù)據(jù)庫

一個MongoDB實例可以支持多個獨(dú)立的 數(shù)據(jù)庫。在使用PyMongo時,您可以使用Mongocl實例上的屬性樣式訪問來訪問數(shù)據(jù)庫:

# 查看當(dāng)前都有那些庫
cl.database_names()

# 獲取數(shù)據(jù)庫對象
db = cl.test_database

或者

db = cl['test_database']

4. 獲取集合

一個集合是一組存儲在MongoDB中的文檔,并且可以被認(rèn)為是大致在關(guān)系數(shù)據(jù)庫中的表。
在 PyMongo 中獲取集合與獲取數(shù)據(jù)庫的工作方式相同:

# 查看當(dāng)前庫中都有那些集合
db.collection_names()

# 獲取集合對象
collection = db.test_collection

# 或者

collection = db['test-collection']

合法的集合名:

  • 集合名不能是空字符串""。
  • 集合名不能含有\(zhòng)0字符(空字符),這個字符表示集合名的結(jié)尾。
  • 集合名不能以"system."開頭,這是為系統(tǒng)集合保留的前綴。
  • 用戶創(chuàng)建的集合名字不能含有保留字符。有些驅(qū)動程序的確支持在集合名里面包含,這是因為某些系統(tǒng)生成的集合中包含該字符。除非你要訪問這種系統(tǒng)創(chuàng)建的集合,否則千萬不要在名字里出現(xiàn)$。

三、惰性機(jī)制

關(guān)于MongoDB中的集合(和數(shù)據(jù)庫)的一個重要注意事項是它們是懶惰地創(chuàng)建的。
上述命令都沒有在MongoDB服務(wù)器上實際執(zhí)行過任何操作。集合和數(shù)據(jù)庫在第一個文檔被插入時創(chuàng)建。

四、 文檔

MongoDB中的數(shù)據(jù)使用JSON樣式的文檔來表示(并存儲)。
在PyMongo中,我們使用字典來表示 Mongo 中文檔。例如,以下字典可能用于表示博客文章:

In [34]: import datetime

In [35]: post = {"author": "yangge",
        "text": "云計算-NoSQL",
        "tags": ["mongodb", "python", "pymongo"],
        "date": datetime.datetime.now()}

請注意,文檔可以包含本機(jī)Python類型(如datetime.datetime實例),這些類型 將自動轉(zhuǎn)換為適當(dāng)?shù)腂SON類型并從其中轉(zhuǎn)換

文檔特點(diǎn):

  • 文檔中的鍵/值對是有序的。
  • 文檔中的值不僅可以是在雙引號里面的字符串,還可以是其他幾種數(shù)據(jù)類型(甚至可以是整個嵌入的文檔)。
  • MongoDB區(qū)分類型和大小寫。
  • MongoDB的文檔不能有重復(fù)的鍵。
  • 文檔的鍵是字符串。除了少數(shù)例外情況,鍵可以使用任意UTF-8字符。

文檔鍵命名規(guī)范:

  1. 鍵不能含有\(zhòng)0 (空字符)。這個字符用來表示鍵的結(jié)尾。
  2. .和$有特別的意義,只有在特定環(huán)境下才能使用。
  3. 以下劃線"_"開頭的鍵是保留的(不是嚴(yán)格要求的)。

五、 插入文件數(shù)據(jù)

# 使用、創(chuàng)建了 posts 集合
In [36]: posts_col = db.posts 

# 向 psts 集合中插入一個文檔,并返回了 _id 對象
In [37]: post_id = posts_col.insert_one(post).inserted_id

In [38]: post_id
Out[38]: ObjectId('5a9f8eb2e138232b02854093')

In [41]: print(post_id)
5a9f8eb2e138232b02854093

In [42]: post_id.__str__()
Out[42]: '5a9f8eb2e138232b02854093'

驗證

插入第一個文檔后,posts集合實際上已經(jīng)在服務(wù)器上創(chuàng)建。

我們可以通過列出數(shù)據(jù)庫中的所有集合來驗證這一點(diǎn):

In [45]: db.collection_names(include_system_collections=False)
Out[45]: ['posts_col']

六、 使用find_one()獲取單個文檔

可以在MongoDB中執(zhí)行的最基本的查詢類型是 find_one()。

此方法返回與查詢匹配的單個文檔(如果沒有匹配,則返回None)。

當(dāng)您知道只有一個匹配的文檔,或者只對第一個匹配感興趣時,它非常有用。

這里我們使用 find_one()從posts集合中獲取第一個文檔:

In [47]: posts_col.find_one()
Out[47]:
{'_id': ObjectId('5a9f8a6de138232b02854092'),
 'author': 'Mike',
 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': 'My first blog post!'}

指定匹配查詢

In [47]: posts_col.find_one(post)
Out[47]:
{'_id': ObjectId('5a9f8eb2e138232b02854093'),
 'author': 'yangge',
 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': '云計算-NoSQL'}
 # --------------------------------------------------

 In [88]: posts_col.find_one({'author': 'yangge'})
Out[88]:
{'_id': ObjectId('5a9f8eb2e138232b02854093'),
 'author': 'yangge',
 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': '云計算-NoSQL'}

最好通過 _id_obj 查找

假如你創(chuàng)建了同樣的數(shù)據(jù)在 Mongo 里,他會同時存在,但是 _id 不一樣。

所以建議使用創(chuàng)建數(shù)據(jù)時返回的 _id 對象來查詢。

In [93]: posts_col.insert_one({"shark": "鯊魚"}).inserted_id
Out[93]: ObjectId('5a9f97d1e138232b02854094')

In [94]: posts_col.insert_one({"shark": "鯊魚"})
Out[94]: <pymongo.results.InsertOneResult at 0x7f74d652e388>

In [95]: shark_id = posts_col.insert_one({"shark": "鯊魚", "age": "18"}).inserted_id

In [96]: shark_id_obj = posts_col.insert_one({"shark": "鯊魚"}).inserted_id

In [97]: posts_col.find_one({"_id": shark_id_obj})
Out[97]: {'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鯊魚'}

In [98]: posts_col.find_one({"_id": shark_id})
Out[98]: {'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鯊魚'}

# 注意有個空格哦
In [99]: posts_col.find_one({"shark": " 鯊魚"})

In [100]: posts_col.find_one({"shark": "鯊魚"})
Out[100]: {'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鯊魚'}

從字符串轉(zhuǎn)換為ObjectId
In [121]: from bson.objectid import ObjectId

In [122]: posts_col.find_one({'_id': ObjectId(shark_id_obj)})
Out[122]: {'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鯊魚'}

==在 Python2 中==

MongoDB以BSON格式存儲數(shù)據(jù)。BSON字符串是UTF-8編碼的,所以PyMongo必須確保它存儲的任何字符串只包含有效的UTF-8數(shù)據(jù)。常規(guī)字符串(<type'str'>)被驗證并保存不變。Unicode字符串(<type'unicode'>)首先被編碼為UTF-8。我們的示例字符串在Python shell中被表示為u'Mike'而不是'Mike',原因是PyMongo將每個BSON字符串解碼為Python unicode字符串,而不是常規(guī)str。

關(guān)于 _id

In [110]: shark_id.generation_time.isoformat()
Out[110]: '2018-03-07T07:42:50+00:00'

七、 批量插入

為了讓查詢更有趣,讓我們插入更多的文檔。除了插入單個文檔外,我們還可以通過將列表作為第一個參數(shù)傳遞給insert_many()來執(zhí)行批量插入操作。這會將每個文檔插入列表中,只向服務(wù)器發(fā)送一條命令:

簡單粗暴的上官方示例

>>> new_posts = [{"author": "Mike",
...               "text": "Another post!",
...               "tags": ["bulk", "insert"],
...               "date": datetime.datetime(2009, 11, 12, 11, 14)},
...              {"author": "Eliot",
...               "title": "MongoDB is fun",
...               "text": "and pretty easy too!",
...               "date": datetime.datetime(2009, 11, 10, 10, 45)}]
>>> result = posts_col.insert_many(new_posts)
>>> result.inserted_ids
[ObjectId('...'), ObjectId('...')]

查詢多個文檔

我們使用find() 方法來獲取多個文檔 。
find() 返回一個 Cursor實例,它允許我們遍歷所有匹配的文檔。

例如,我們可以迭代posts集合中的每個文檔:

In [129]: for post in posts_col.find():
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f8a6de138232b02854092'), 'author': 'Mike', 'text': 'My first blog post!', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000)}
{'_id': ObjectId('5a9f8eb2e138232b02854093'), 'author': 'yangge', 'text': '云計算-NoSQL', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000)}
{'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f97e1e138232b02854095'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f9e48e138232b02854098'), 'author': 'Mike', 'text': 'Another post!', 'tags': ['bulk', 'insert'], 'date': datetime.datetime(2009, 11, 12, 11, 14)}
{'_id': ObjectId('5a9f9e48e138232b02854099'), 'author': 'Eliot', 'title': 'MongoDB is fun', 'text': 'and pretty easy too!', 'date': datetime.datetime(2009, 11, 10, 10, 45)}

就像我們用 find_one()所做的那樣,我們可以傳遞一個文檔給 find() 來限制返回的結(jié)果。
在這里,我們只得到那些作者是 "鯊魚" 的文檔:

In [133]: for post in posts_col.find({"shark": '鯊魚'}):
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f97e1e138232b02854095'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鯊魚'}
{'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鯊魚'}

計數(shù)

In [134]: posts_col.count()
Out[134]: 8

In [135]: posts_col.find({"author": "yangge"}).count()
Out[135]: 1

范圍查詢

MongoDB支持許多不同類型的高級查詢。例如,讓我們執(zhí)行查詢,將結(jié)果限制為比特定日期更早的帖子,還可以按作者對結(jié)果進(jìn)行排序

In [136]: d = datetime.datetime(2018, 11, 12, 12)

In [137]:  for post in posts_col.find({"date": {"$lt": d}}).sort("author"):
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f9e48e138232b02854099'), 'author': 'Eliot', 'title': 'MongoDB is fun', 'text': 'and pretty easy too!', 'date': datetime.datetime(2009, 11, 10, 10, 45)}
{'_id': ObjectId('5a9f8a6de138232b02854092'), 'author': 'Mike', 'text': 'My first blog post!', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000)}
{'_id': ObjectId('5a9f9e48e138232b02854098'), 'author': 'Mike', 'text': 'Another post!', 'tags': ['bulk', 'insert'], 'date': datetime.datetime(2009, 11, 12, 11, 14)}
{'_id': ObjectId('5a9f8eb2e138232b02854093'), 'author': 'yangge', 'text': '云計算-NoSQL', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000)}

排序

db.mycollection
mycol = db.mycollection
mycol.insert_one({'name': '姜文'})
result_dic = db.mycollection.find().sort("age")
for item in result_dic:
    print(item)

更新

更新數(shù)據(jù)庫, ObjectId 需要引入

from bson.objectid import ObjectId
db.mycollection.update({'_id': ObjectId('59255118d92fac43dcb1999a')}, {'$set': {'name': '九筒'}})

刪除

刪除指定數(shù)據(jù)

db.mycollection.remove({'name':'王二麻33333'})

刪除全部數(shù)據(jù)(慎用)

db.mycollection.remove()

### capped collections (擴(kuò)展)

Capped collections 就是固定大小的collection。

它有很高的性能以及隊列過期的特性(過期按照插入的順序). 有點(diǎn)和 "RRD" 概念類似。

Capped collections是高性能自動的維護(hù)對象的插入順序。它非常適合類似記錄日志的功能 和標(biāo)準(zhǔn)的collection不同,你必須要顯式的創(chuàng)建一個capped collection, 指定一個collection的大小,單位是字節(jié)。collection的數(shù)據(jù)存儲空間值提前分配的。

要注意的是指定的存儲大小包含了數(shù)據(jù)庫的頭信息。

db.createCollection("mycoll", {capped:true, size:100000})

  • 在capped collection中,你能添加新的對象。
  • 能進(jìn)行更新,然而,對象不會增加存儲空間。如果增加,更新就會失敗 。
  • 數(shù)據(jù)庫不允許進(jìn)行刪除。使用drop()方法刪除collection所有的行。
  • 注意: 刪除之后,你必須顯式的重新創(chuàng)建這個collection。
  • 在32bit機(jī)器中,capped collection最大存儲為1e9( 1X109)個字節(jié)。

元數(shù)據(jù)

數(shù)據(jù)庫的信息是存儲在集合中。它們使用了系統(tǒng)的命名空間:

dbname.system.*

在MongoDB數(shù)據(jù)庫中名字空間 <dbname>.system.* 是包含多種系統(tǒng)信息的特殊集合(Collection),如下:

集合命名空間 描述
dbname.system.namespaces 列出所有名字空間。
dbname.system.indexes 列出所有索引。
dbname.system.profile 包含數(shù)據(jù)庫概要(profile)信息。
dbname.system.users 列出所有可訪問數(shù)據(jù)庫的用戶。
dbname.local.sources 包含復(fù)制對端(slave)的服務(wù)器信息和狀態(tài)。

對于修改系統(tǒng)集合中的對象有如下限制。

  • {{system.indexes}} 插入數(shù)據(jù),可以創(chuàng)建索引。

  • 但除此之外該表信息是不可變的(特殊的 drop index 命令將自動更新相關(guān)信息)。

  • {{system.users}} 是可修改的。

  • {{system.profile}} 是可刪除的。


MongoDB 數(shù)據(jù)類型

下表為MongoDB中常用的幾種數(shù)據(jù)類型。

數(shù)據(jù)類型 描述
String 字符串。存儲數(shù)據(jù)常用的數(shù)據(jù)類型。在 MongoDB 中,UTF-8 編碼的字符串才是合法的。
Integer 整型數(shù)值。用于存儲數(shù)值。根據(jù)你所采用的服務(wù)器,可分為 32 位或 64 位。
Boolean 布爾值。用于存儲布爾值(真/假)。
Double 雙精度浮點(diǎn)值。用于存儲浮點(diǎn)值。
Min/Max keys 將一個值與 BSON(二進(jìn)制的 JSON)元素的最低值和最高值相對比。
Array 用于將數(shù)組或列表或多個值存儲為一個鍵。
Timestamp 時間戳。記錄文檔修改或添加的具體時間。
Object 用于內(nèi)嵌文檔。
Null 用于創(chuàng)建空值。
Symbol 符號。該數(shù)據(jù)類型基本上等同于字符串類型,但不同的是,它一般用于采用特殊符號類型的語言。
Date 日期時間。用 UNIX 時間格式來存儲當(dāng)前日期或時間。你可以指定自己的日期時間:創(chuàng)建 Date 對象,傳入年月日信息。
Object ID 對象 ID。用于創(chuàng)建文檔的 ID。
Binary Data 二進(jìn)制數(shù)據(jù)。用于存儲二進(jìn)制數(shù)據(jù)。
Code 代碼類型。用于在文檔中存儲 JavaScript 代碼。
Regular expression 正則表達(dá)式類型。用于存儲正則表達(dá)式。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 古龍的作品 江南煙雨春光好,把酒疏狂暢尋歡 月異蒼穹湘妃引,護(hù)花失魂缺玉環(huán) 一曲神來留香久,鐵血錚骨大旗翩 風(fēng)云驚...
    唐詩0525閱讀 351評論 0 0
  • 最近讀了瑞·達(dá)利歐的《原則》一書,為作者在書中的觀點(diǎn)和哲理所折服。達(dá)利歐是橋水基金的創(chuàng)始人,橋水基金被稱為是全球最...
    楚焽閱讀 611評論 0 5
  • 迷茫時,就盡情去堅持你所熱愛的。 也許在你堅持夢想目標(biāo)的路上,會有很多人嘲笑你,也會有走不出的困境;但只要克服下來...
    笨蛋小姐傻瓜先生閱讀 332評論 0 1

友情鏈接更多精彩內(nèi)容