這是本人翻譯的PyMongo官方文檔。如今網上分(抄)享(襲)的PyMongo博客文章不少,一方面這些文章本就是抄襲的,談不上什麼格式美觀,另外一方面其實這些博客已經落後好久了,根本是不能做爲參考的。遂本身翻譯了一下。渣翻譯請見諒,能看懂就行。
本翻譯文檔包含如下內容:html
- 使用PyMongo插入數據
- 使用PyMongo查詢數據
- 使用PyMongo更新數據
- 使用PyMongo刪除數據
- 使用PyMongo進行數據聚合
- 使用PyMongo建立索引
原文地址見連接:原文地址python
PyMongo是一個用於MongoDB的Python工具,也是一個被推薦的Python操做MongoDB數據庫的方式。linux
你能夠只用pip工具安裝:mongodb
pip install pymongo
使用Windows安裝工具,詳見https://pypi.python.org/pypi/pymongo/。shell
在一個Python交互shell中完成此過程,或者也能夠在其餘Python環境中完成,例如Python腳本、Python模塊、Python項目。數據庫
從pymongo中引入MongoClicent。windows
from pymongo import MongoClient
使用MongoClient建立一個鏈接:api
client = MongoClient()
若是你沒有特別爲MongoClient指定參數,MongoClient將使用MongoDB默認參數即localhost接口和27017端口。數組
你可使用一個完整的MongoDB URI來定義鏈接:app
client = MongoClient("mongodb://mongodb0.example.net:27019")
這個MongoClient表明了一個運行於mongodb.example.net端口號爲27019的MongoDB鏈接。
第一個你用pymongo來交互的基本類是Database
,它表明了MongoDB中的數據庫(database)結構。數據庫保存了邏輯上相關的集合組。MongoDB將在第一次使用新的數據庫的時候自動建立它。
你可使用屬性訪問的方式,賦值一個數據庫(例如名字爲primer
)給本地變量db
,以下所示:
db = client.primer
你也可使用字典形式訪問一個數據庫,這會移除Python特有的命名限制,以下所示:
db = client['primer']
第二個你將使用pymongo進行交互的基本類是Collection
,它表明了MongoDB中的集合(collection)結構。集合(collection)保存了邏輯上相關的文檔組。
你能夠直接使用字典形式訪問集合或者經過一個訪問一個數據庫對象的屬性來訪問集合,以下所示:
db.dataset db['dataset']
你也能夠給一個變量進行賦值,以在其餘地方使用這個集合,以下所示:
coll = db.dataset coll = db['dataset']
你可使用insert_one()
方法和insert_many()
方法來向MongoDB的集合中插入文檔。若是你所插入的集合在MongoDB中不存在,MongoDB將爲你自動建立一個集合。
在Python命令行或者IDLE中,使用MongoClient鏈接一個正在運行的MongoDB實例,且已經打開test
數據庫。
from pymongo import MongoClient client = MongoClient() db = client.test
向集合restaurants
中插入一個文檔。若是集合不存在,這個操做將建立一個新的集合。
from datetime import datetime result = db.restaurants.insert_one( { "address": { "street": "2 Avenue", "zipcode": "10075", "building": "1480", "coord": [-73.9557413, 40.7720266] }, "borough": "Manhattan", "cuisine": "Italian", "grades": [ { "date": datetime.strptime("2014-10-01", "%Y-%m-%d"), "grade": "A", "score": 11 }, { "date": datetime.strptime("2014-01-16", "%Y-%m-%d"), "grade": "B", "score": 17 } ], "name": "Vella", "restaurant_id": "41704620" } )
這個操做返回了一個InsertOneResult對象,它包括了insert_id
屬性表示被插入的文檔的_id
。訪問insert_id
的方式以下:
result.inserted_id
你插入的文檔的ObjectId將和以下所示的不一樣。
ObjectId("54c1478ec2341ddf130f62b7")
若是你傳遞給insert_one()
方法的參數不包含_id
字段,MongoClient將自動添加這個字段而且生成一個ObjectId設置爲這個字段的值。
你能夠經過find()
方法產生一個查詢來從MongoDB的集合中查詢到數據。MongoDB中全部的查詢條件在一個集合中都有一個範圍。
查詢能夠返回在集合中的全部數據或者只返回符合篩選條件(filter)或者標準(criteria)的文檔。你能夠在文檔中指定過濾器或者標準,並做爲參數傳遞給find()
方法。
find()
方法返回一個查詢結果的遊標,這是一個產生文檔的迭代對象。
本示例中使用test
數據庫中的restaurants
集合。與使用示例數據填充集合有關的介紹請見Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient鏈接一個正在運行的MongoDB實例,且已經打開test
數據庫。
from pymongo import MongoClient client = MongoClient() db = client.test
調用find()
方式不須要傳值便可獲得集合中全部的文檔。舉例來講,以下所示的操做便是返回restaurants
集合中全部文檔。
cursor = db.restaurants.find()
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果包含了全部restaurants
集合中的全部文檔。
對某一個字段的相等條件查詢有以下形式:
{ <field1>: <value1>, <field2>: <value2>, ... }
若是字段(<field>
)在某個文檔的某一個數組內,則使用點操做符(dot notation)去訪問該字段。
以下所示的操做將查詢borough
字段等於Manhattan
的文檔。
cursor = db.restaurants.find({"borough": "Manhattan"})
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將只包含符合條件的文檔。
要指定嵌入文檔中的字段的查詢條件,須要使用點操做符。使用點操做符須要使用雙引號將字段名包裹。下面的操做將指定一個文檔的地址字典中的郵編字段的一個相等的條件。
cursor = db.restaurants.find({"address.zipcode": "10075"})
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將只包含符合條件的文檔。
更多的關於嵌入式文檔的查詢條件信息,請參閱Embedded Documents。
grades
數組包含一個嵌入式文檔做爲其元素。在該文檔的字段上指定一個相等條件須要用到點操做符。使用點操做符須要使用雙引號將字段名包裹。以下所示的查詢將查詢一個有嵌入式文檔的grades
字段,該字段中的grade
等於B
。
cursor = db.restaurants.find({"grades.grade": "B"})
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將只包含符合條件的文檔。
更多的關於數組內查詢條件的信息,例如數組中特殊的混合條件,請參閱Array及$elemMatch操做符。
MongoDB支持使用操做符指定查詢條件,例如比較操做符。雖然這其中有一些例外,例如$or
和$and
條件操做符。使用操做符進行查詢通常有以下形式:
{ <field1>: { <operator1>: <value1> } }
完整的操做符列表請查閱query opeartors
(http://docs.mongodb.org/manual/reference/operator/query)。
查詢字段grades
包含一個嵌入式文檔,其中score
大於30。
cursor = db.restaurants.find({"grades.score": {"$gt": 30}})
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將只包含符合條件的文檔。
查詢字段grades
包含一個嵌入式文檔,其中score
小於10。
cursor = db.restaurants.find({"grades.score": {"$lt": 10}})
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將只包含符合條件的文檔。
你可使用邏輯與(AND)或者邏輯或(OR)組合多個查詢條件。
你可使用一個列表指定一個邏輯與條件查詢操做,使用逗號分隔條件。
cursor = db.restaurants.find({"cuisine": "Italian", "address.zipcode": "10075"})
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將只包含符合條件的文檔。
你可使用$or
操做符進行邏輯或條件的指定。
cursor = db.restaurants.find( {"$or": [{"cuisine": "Italian"}, {"address.zipcode": "10075"}]})
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將只包含符合條件的文檔。
要指定結果集的順序,能夠經過追加sort()
方法進行查詢。給sort()
方法傳遞須要排序的字段和配需類型等。
pymongo.ASCENDING
表示升序排序。pymongo.DESCENDING
表示降序排序。若是要經過多個鍵星星排序,能夠傳遞鍵的列表和以及對應的排序類型的列表。舉例來講,以下操做將返回restaurants
集合中全部的文檔,而且先經過borough
字段進行升序排序,而後在每一個borough
內,經過"address.zipcode"
字段進行升序排序。
import pymongo cursor = db.restaurants.find().sort([ ("borough", pymongo.ASCENDING), ("address.zipcode", pymongo.ASCENDING) ])
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將只包含符合條件且通過排序的文檔。
你可使用update_one()
和update_many
方法更新集合中的文檔。update_one()
方法一次更新一個文檔。使用update_many()
方法能夠更新全部符合條件的文檔。方法接受如下三個參數:
要指定更新時的過濾器,使用和查詢條件時相同的結構便可。參見使用PyMongo查詢數據獲取查詢條件的信息。
你不能更新_id
字段。
本示例中使用test
數據庫中的restaurants
集合。與使用示例數據填充集合有關的介紹請見Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient鏈接一個正在運行的MongoDB實例,且已經打開test
數據庫。
from pymongo import MongoClient client = MongoClient() db = client.test
要改變一個特定字段的值,MongoDB提供了更新操做符,例如$set
操做符能夠修改值。例如$set
之類的操做符將在沒有該字段的時候新建這個字段。能夠查閱update operators做爲參考。
以下操做將更新第一個符合name
等於Juni
這個條件的文檔。使用$set
操做符更新cuisine
字段且將lastModified
修改成當前日期。
result = db.restaurants.update_one( {"name": "Juni"}, { "$set": { "cuisine": "American (New)" }, "$currentDate": {"lastModified": True} } )
這個操做返回了一個UpdateResult對象。這個對象報告了符合條件的文檔數目以及被修改的文檔數目。
要查看符合篩選器條件的文檔數目,經過訪問UpdateResult
對象的matched_count
屬性。
result.matched_count
matched_count
值爲:
1
要查看更新操做中被修改的文檔數目,經過訪問UpdateResult
對象的modified_count
屬性。
modified_count
值爲:
1
要更新一個嵌入式文檔中的字段,須要使用點操做符。當使用點操做符時,使用點操做符須要使用雙引號將字段名包裹。下面的操做將更新address
字段中的street
值。
result = db.restaurants.update_one( {"restaurant_id": "41156888"}, {"$set": {"address.street": "East 31st Street"}} )
這個操做返回了一個UpdateResult
對象。這個對象報告了符合條件的文檔數目以及被修改的文檔數目。
要查看符合篩選器條件的文檔數目,經過訪問UpdateResult
對象的matched_count
屬性。
result.matched_count
matched_count
值爲:
1
要查看更新操做中被修改的文檔數目,經過訪問UpdateResult
對象的modified_count
屬性。
modified_count
值爲:
1
update_one()
方法更新了一個文檔,要更新多個文檔,須要使用update_many()
方法。下面的操做將更新全部的address.zipcode
等於10016
以及cuisine
等於Other
的文檔,將cuisine
字段設置爲Category To Be Determined
以及將lastModified
更新爲當前日期。
result = db.restaurants.update_many( {"address.zipcode": "10016", "cuisine": "Other"}, { "$set": {"cuisine": "Category To Be Determined"}, "$currentDate": {"lastModified": True} } )
這個操做返回了一個UpdateResult
對象。這個對象報告了符合條件的文檔數目以及被修改的文檔數目。
要查看符合篩選器條件的文檔數目,經過訪問UpdateResult
對象的matched_count
屬性。
result.matched_count
matched_count
值爲:
20
要查看更新操做中被修改的文檔數目,經過訪問UpdateResult
對象的modified_count
屬性。
modified_count
值爲:
20
要替換整個文檔(除了_id
字段),將一個完整的文檔做爲第二個參數傳給update()
方法。替代文檔對應原來的文檔能夠有不一樣的字段。在替代文檔中,你能夠忽略_id
字段由於它是不變的。若是你包含了_id
字段,那它必須和原文檔的值相同。
重要:
在更新以後,該文檔將只包含替代文檔的字段。
在以下的更新操做後,被修改的文檔將只剩下_id
、name
和address
字段。該文檔將再也不包含restaurant_id
、cuisine
、grades
以及borough
字段。
result = db.restaurants.replace_one( {"restaurant_id": "41704620"}, { "name": "Vella 2", "address": { "coord": [-73.9557413, 40.7720266], "building": "1480", "street": "2 Avenue", "zipcode": "10075" } } )
replace_one
操做返回了一個UpdateResult
對象。這個對象報告了符合條件的文檔數目以及被修改的文檔數目。
要查看符合篩選器條件的文檔數目,經過訪問UpdateResult
對象的matched_count
屬性。
result.matched_count
matched_count
值爲:
20
要查看更新操做中被修改的文檔數目,經過訪問UpdateResult
對象的modified_count
屬性。
modified_count
值爲:
20
你可使用delete_one()
以及delete_many()
方法從集合中刪除文檔。方法須要一個條件來肯定須要刪除的文檔。
要指定一個刪除條件,使用和查詢條件時相同的結構便可。參見使用PyMongo查詢數據獲取查詢條件的信息。
本示例中使用test
數據庫中的restaurants
集合。與使用示例數據填充集合有關的介紹請見Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient鏈接一個正在運行的MongoDB實例,且已經打開test
數據庫。
from pymongo import MongoClient client = MongoClient() db = client.test
下面的操做將刪除全部複合條件的文檔。
result = db.restaurants.delete_many({"borough": "Manhattan"})
這個操做返回了一個DeleteResult對象。這個對象報告了被刪除的文檔數目。
要查看被刪除的文檔數目,經過訪問DeleteResult
對象的deleted_count
屬性。
result.deleted_count
deleted_count
值爲:
10259
若是你已經插入或者更新了文檔,那麼你獲得的結果將和示例不一樣。
要刪除一個集合中的全部文檔,給delete_many()
方法傳遞一個空的條件參數便可。
result = db.restaurants.delete_many({})
這個操做返回了一個DeleteResult對象。這個對象報告了被刪除的文檔數目。
要查看被刪除的文檔數目,經過訪問DeleteResult
對象的deleted_count
屬性。
result.deleted_count
deleted_count
值爲:
15100
若是你已經插入或者更新了文檔,那麼你獲得的結果將和示例不一樣。
刪除全部文檔的操做只會清空集合中的文檔。該集合以及集合的索引將依舊存在。要清空一個集合,銷燬該集合以及它的索引而且重建集合和索引多是相比於清空一個集合更加高效的操做方式。使用drop()
方法能夠銷燬一個集合,包括它全部的索引。
db.restaurants.drop()
MongoDB能夠進行數據聚合操做,例如能夠針對某一字段進行分組或者對某一字段不一樣的值進行統計。
使用aggregate()
方法可使用基於步驟的聚合操做。appregate()
方法接受多個數組做爲每一步的操做。每個階段按照順序處理,描述了對數據操做的步驟。
db.collection.aggregate([<stage1>, <stage2>, ...])
這部分的例子使用了test
數據庫中的restaurants
集合。須要查看在集合中填充的實例數據,請參閱Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient鏈接一個正在運行的MongoDB實例,且已經打開test
數據庫。
from pymongo import MongoClient client = MongoClient() db = client.test
使用$group
操做符去利用一個指定的鍵進行分組。在$group
操做中,指定須要分組的字段爲_id
。$group
經過字段路徑訪問字段,該字段須要有一個美圓符號$
做爲前綴。$group
操做可使用累加器對本次分組進行計算。下面的例子將使用borough
字段對restaurants
集合進行操做,而且使用$sum
累加器進行文檔的統計計算。
cursor = db.restaurants.aggregate( [ {"$group": {"_id": "$borough", "count": {"$sum": 1}}} ] )
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將由以下文檔組成:
{u'count': 969, u'_id': u'Staten Island'} {u'count': 6086, u'_id': u'Brooklyn'} {u'count': 10259, u'_id': u'Manhattan'} {u'count': 5656, u'_id': u'Queens'} {u'count': 2338, u'_id': u'Bronx'} {u'count': 51, u'_id': u'Missing'}
_id
字段包含了不一樣的borough
值,即根據鍵的值進行了分組。
使用$match
操做來刪選文檔。$match
使用MongoDB查詢語法。下面的管道使用$match
來對restaurants
進行一個borough
等於"Queens"
且cuisine
等於Brazilian
的查詢。接着$group
操做對命中的文檔使用address.zipcode
字段分組並使用$sum
進行統計。$group
經過字段路徑訪問字段,該字段須要有一個美圓符號$
做爲前綴。
cursor = db.restaurants.aggregate( [ {"$match": {"borough": "Queens", "cuisine": "Brazilian"}}, {"$group": {"_id": "$address.zipcode", "count": {"$sum": 1}}} ] )
迭代遊標(cursor)而且打印文檔內容。
for document in cursor: print(document)
結果將由以下文檔組成:
{u'count': 1, u'_id': u'11368'} {u'count': 3, u'_id': u'11106'} {u'count': 1, u'_id': u'11377'} {u'count': 1, u'_id': u'11103'} {u'count': 2, u'_id': u'11101'}
_id
字段包含了不一樣的zipcode
值,即根據鍵的值進行了分組。
索引能夠對查詢的高效執行起到支持。若是沒有索引,MongoDB必須進行全表掃描,即掃描集合中的每一個文檔,來選擇符合查詢條件的文檔。若是一個適當的索引存在於一個查詢中,MongoDB可使用索引限制必須檢查文檔的數量。
使用create_index()
方法來爲一個集合建立索引。因此能夠對查詢的高效執行起到支持。MongoDB會在建立文檔的時候自動爲_id
字段建立索引。
要爲一個或多個字段建立索引,使用一個包含字段和索引類型的列表做爲參數:
[ ( <field1>: <type1> ), ... ]
pymongo.ASCENDING
爲索引類型(
pymongo.DESCENDING
爲索引類型(
create_index()
只會在索引不存在的時候建立一個索引。
下面的例子將使用test
數據庫中的restaurants
集合。須要查看在集合中填充的實例數據,請參閱Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient鏈接一個正在運行的MongoDB實例,且已經打開test
數據庫。
from pymongo import MongoClient client = MongoClient() db = client.test
在restaurants
集合中的cuisine
字段上建立自增的索引。
import pymongo db.restaurants.create_index([("cuisine", pymongo.ASCENDING)])
該方法將返回被建立的索引的名字。
"u'cuisine_1'"
MongoDB支持在多個字段上建立符合索引。這幾個字段的命令將聲明這個索引包含的鍵。舉個例子,下面的操做將在cuisine
字段和address.zipcode
字段上建立一個複合索引。該索引將先對cuisine
的值輸入一個升序的命令,而後對address.zipcode
的值輸入一個降序命令。
import pymongo db.restaurants.create_index([ ("cuisine", pymongo.ASCENDING), ("address.zipcode", pymongo.DESCENDING) ])
該方法將返回被建立的索引的名字。
"u'cuisine_1_address.zipcode_-1'"