原版英文文檔html
這個教程只在介紹如何使用MongoDB和PyMongopython
在咱們開始以前,首先確認你已經正確安裝了PyMongo ,在python shell 中若是下面的命令沒有報錯,則證實安裝正確web
>>>import pymongo
這個教程假設你已經正確安裝了MongoDB,並且已經有一個instance運行在默認的host和port,若是你已經正確安裝了mongodb可使用下面進行啓動mongodb
$mongod
使用pymongo的第一步是建立一個MongoClient 用於和運行的mongod實例進行鏈接shell
>>>from pymongo import MongoClient >>>client = MongoClient()
上面的代碼將會鏈接默認的Host和port.咱們也能夠手動指定host 和端口,好比:數據庫
>>>client = MongoClient('localhost',27017)
或者使用mongodb url 格式地址:api
>>>client = MongoClient('mongodb://localhost:27017/')
一個mongodb實例能夠支持多個獨立的databse. 當使用pymongo的時候,你可使用相似屬性風格的方式訪問MongoClient實例的database:服務器
>>>db = client.test_database
或者使用字典風格也能夠數據結構
>>>db = client['test-database']
一個集合(collection)是一系列儲存在mongodb上的文檔(document)的組,有點相似關係型數據庫的表table。獲取集合的方法相似獲取數據庫post
>>>collection = db.test_collection
或者使用字典:
>>>collection = db['test-collection']
須要注意的是mongodb中的databases或者documents都是屬於延遲建立(lazily created)的,上面全部的commands其實都沒有對數據庫進行任何實質性的操做。上面代碼中的databases或者documents直到第一個documents被添加insert時才被建立
數據在mongodb裏面以JSON風格文檔來存儲和體現。在pymongo中咱們使用字典來體現documents。在下面的例子中字典被用來表現一篇博客:
>>>import datetime: >>>post = {"author":"Mike", "text":"My first blog post", "tags"["mongodb",'python','pymongo'], "date": datetime.datetime.utcnow()}
注意 documents能夠包含python本身的類型(好比datetime.datetime實例),這些數據會被自動轉化爲bson類型
可使用insert_one()來添加一條documents:
>>>posts = db.posts >>>post_id = posts.insertone(post).inserted_id >>>post_id ObjectId('...')
當添加documents時候,若是‘_id’值沒有指定,則系統會自動生成一個'_id'值,這個'_id'值在整個collection中是惟一的。inssert_one()返回一個InsertOneResult結果實例。
在添加了第一個document時,posts這個集合纔在服務器上真正的建立。咱們能夠列出database中的集合collection來確認:
>>>db.collection_names(include_system_collections=False) [u'posts']
最常使用的查詢就是find_one()。他返回一條匹配的文檔(若是沒有匹配會返回None)。他常常被用在只有一條文檔匹配,或者指向獲得第一個匹配文檔的狀況。下面咱們用他來返回post集合的第一條文檔:
>>>posts.finde_one() {u'date':datetime.datetime(...),u'text':u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
返回的結果就是咱們剛纔添加的那條文檔
注意:返回的文檔中包含"_id",這是系統自動生成的
能夠給find_one()添加一些匹配的參數:
>>>posts.find_one({'author':"mike"}) {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
若是咱們嘗試一個不一樣的author,好比‘Eliot’就得不到結果:
>>> posts.find_one({"author": "Eliot"}) >>>
咱們也能夠經過ObjectId進行查詢:
>>> post_id ObjectId(...) >>> posts.find_one({"_id": post_id}) {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
注意ObjectId並非一個簡單的string
>>> post_id_as_str = str(post_id) >>> posts.find_one({"_id": post_id_as_str}) # No result >>>
當咱們進行web開發的時候,常常會須要將url中獲得的ObjectId轉換成pymongo能夠識別的ObjectId,而後將他傳遞給find_one: from bson.objectid import OjbectId # The web framework gets post_id from the URL and passes it as a string def get(post_id): #Convert from string to ObjectId: document = client.db.collection.find_one({'_id': ObjectId(post_id)})
你可能已經發現了咱們剛纔保存的常規的Python string和咱們從服務器獲得的並不同(好比u'Mike' 'Mike'),這裏咱們簡單的解釋一下:
mongodb保存使用BSON 格式來保存數據。BSON string 都是UTF-8編碼,因此pymongo必須確保全部的sting必須都是合法的UTF-8數據。常規的string儲存不變???(regular string are validated and stored unaltered), Unicode編碼的string首先會已utf-8編碼。咱們例子裏面顯示爲u'Mike'而不是'Mike'的緣由就是,pymongo首先解碼每一個BSON爲PYHON unicode string,而不是常規的str (媽的,不懂)
可使用insert_many() 一次性添加多個document
>>> 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.insert_many(new_posts) >>> result.inserted_ids [ObjectId('...'), ObjectId('...')]
關於上面這個例子須要注意兩點:
咱們可使用find()來一次性返回多個文檔。find()返回一個指針cursor實例,能夠用來遍歷全部匹配的documents。 例如我能夠用它來遍歷全部的posts集合的全部documents:
>>>for post in posts.find(): ... post ... {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']} {u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']} {u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'}
就像find_one()同樣,咱們也能夠給他傳遞參數
>>> for post in posts.find({"author": "Mike"}): ... post ... {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']} {u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']}
可使用count()方法進行計數,而不是返回一個完整的查詢
>>> posts.count() 3
或者對返回的查詢進行計數
>>> posts.find({"author": "Mike"}).count() 2
mongodb支持多種不一樣類型的高級查詢。好比我能夠查詢一個早於特定時間的posts,而後按照author排序返回
>>> d = datetime.datetime(2009, 11, 12, 12) >>> for post in posts.find({"date": {"$lt": d}}).sort("author"): ... print post ... {u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'} {u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']}
這裏咱們使用「$lt」操做符來作一個範圍查詢,而後使用sort()來對結果進行排序
若是想讓上述查詢更快,咱們能夠給「date」 和"author"屬性增長 元素索引。 爲了顯示增長索引後的效率提高,咱們使用explain()方法來獲得查詢動做的次數:
>>> posts.find({"date": {"$lt": d}}).sort("author").explain()["cursor"] u'BasicCursor' >>> posts.find({"date": {"$lt": d}}).sort("author").explain()["nscanned"] 3
能夠看到在沒有索引的狀況下,使用 基本指針basicCursor 總共掃描了集合中的3個文檔,如今咱們添加索引
>>>from pymongo import ASCENDING, DESCENDING >>>posts.create_index([("date", DESCENDING), ("author"), ASCENDING]) u'date_-1_author_1' >>>posts.find({'date':{"$lt":d}}).sort("author").explain(['curosr']) u'BtreeCursor date_-1_author_1 >>> posts.find({"date": {"$lt": d}}).sort("author").explain()["nscanned"] 2
能夠看到此次的衩裙使用 Btree指針 BtreeCursor 只掃描了兩個文檔就獲得告終果