pymongo tutorial

原版英文文檔html

教程

這個教程只在介紹如何使用MongoDBPyMongopython

準備前提

在咱們開始以前,首先確認你已經正確安裝了PyMongo ,在python shell 中若是下面的命令沒有報錯,則證實安裝正確web

>>>import pymongo

這個教程假設你已經正確安裝了MongoDB,並且已經有一個instance運行在默認的host和port,若是你已經正確安裝了mongodb可使用下面進行啓動mongodb

$mongod

和MongoClient創建鏈接

使用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/')

獲取數據庫(Database)

一個mongodb實例能夠支持多個獨立的databse. 當使用pymongo的時候,你可使用相似屬性風格的方式訪問MongoClient實例的database:服務器

>>>db  = client.test_database

或者使用字典風格也能夠數據結構

>>>db = client['test-database']

獲取一個集合(collection)

一個集合(collection)是一系列儲存在mongodb上的文檔(document)的組,有點相似關係型數據庫的表table。獲取集合的方法相似獲取數據庫post

>>>collection = db.test_collection

或者使用字典:

>>>collection = db['test-collection']

須要注意的是mongodb中的databases或者documents都是屬於延遲建立(lazily created)的,上面全部的commands其實都沒有對數據庫進行任何實質性的操做。上面代碼中的databases或者documents直到第一個documents被添加insert時才被建立

文檔(documents)

數據在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 a document)

可使用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()來獲得一條document

最常使用的查詢就是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查詢

咱們也能夠經過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)})

關於Unicode

你可能已經發現了咱們剛纔保存的常規的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 (媽的,不懂)

關於pythong unicode string的詳細閱讀

批量添加 Bulk inserts

可使用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('...')]

關於上面這個例子須要注意兩點:

  • 上面例子中insert_many()反悔了兩個ObjectId實例,分別對應兩個document
  • new_posts[1] 和其餘的post的數據結構「shape」是不一樣的 - 一個有tag屬性,一個有title屬性,這就是咱們常提到mongodb的自由結構(schema-free)特性 區別於傳統的關係型數據庫

查詢獲得多個文檔

咱們可使用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 只掃描了兩個文檔就獲得告終果

相關文章
相關標籤/搜索