Python+Mongodb 案例解析

本教程適合于mongodb的創(chuàng)建/查詢(xún)/和基本的案例操作

注:未經(jīng)許可不得轉(zhuǎn)載

一、配置和安裝相應(yīng)的環(huán)境

主要針對(duì)python腳本操作mongdb數(shù)據(jù)庫(kù),所以安裝pymongo和mongodb庫(kù)。安裝教程請(qǐng)谷歌;

二、創(chuàng)建連接到mongodb數(shù)據(jù)庫(kù):

與PyMongo工作時(shí),第一步是建立一個(gè)MongoClient到正在運(yùn)行的mongod實(shí)例。

>>>from pymongo import MongoClient

>>>client = MongoClient('localhost', 27017)#比較常用

>>># client = MongoClient('mongodb://localhost:27017/')使用MongoDB的URI格式

創(chuàng)建常見(jiàn)的方式有兩種:一種是連接到默認(rèn)的主機(jī)端口;另外一種是指定主機(jī)和固定的端口,注意一般mongodb安裝時(shí)默認(rèn)的端口為:27017。

三、創(chuàng)建數(shù)據(jù)庫(kù)

MongoDB中的單個(gè)實(shí)例可以支持多個(gè)獨(dú)立的數(shù)據(jù)庫(kù)。當(dāng)PyMongo工作訪問(wèn)使用上MongoClient實(shí)例屬性的風(fēng)格訪問(wèn)數(shù)據(jù)庫(kù):例如創(chuàng)建一個(gè)test_database數(shù)據(jù)庫(kù)。

>>>db = client.test_database

>>># db = client['test-database']或者這種形式

>>>#test_database數(shù)據(jù)庫(kù)的名稱(chēng)

四、獲取集合(getting a collection)

集合是一組存儲(chǔ)在MongoDB中的文件,并且可以被認(rèn)為是一個(gè)表,作為大致在關(guān)系數(shù)據(jù)庫(kù)中的等效的。獲得在PyMongo收集工作與獲取數(shù)據(jù)庫(kù):

>>>collection = db.test_collection

>>># collection = db['test-collection']或者這種形式

有關(guān)集合(和數(shù)據(jù)庫(kù))在MongoDB中一個(gè)重要的注意的是:當(dāng)?shù)谝粋€(gè)文件被插入到他們集合和數(shù)據(jù)庫(kù)時(shí)集合就被創(chuàng)建。

五、文件

MongoDB中的數(shù)據(jù)是使用JSON風(fēng)格的文件代表(和存儲(chǔ))。在PyMongo我們用字典來(lái)代表文件。作為一個(gè)例子,下面的字典可能被用來(lái)代表一個(gè)博客帖子,下面以一個(gè)例子來(lái)說(shuō)明文件的寫(xiě)入mongodb的過(guò)程:

文件的內(nèi)如如下:

>>> import datetime

>>> post = {"author": "Mike",

..."text":"My first blog post!",

..."tags":["mongodb", "python", "pymongo"],

..."date":datetime.datetime.utcnow()}

Note:請(qǐng)注意,文檔可以包含原生的Python類(lèi)型(如datetime.datetime實(shí)例),它會(huì)自動(dòng)轉(zhuǎn)換,并從相應(yīng)的BSON類(lèi)型。

5.1文件的插入

若要將文檔轉(zhuǎn)換為集合,可以使用insert_one()函數(shù)進(jìn)行:

>>> posts = db.posts

>>> post_id = posts.insert_one(post).inserted_id

>>> post_id

Out[5]: ObjectId('56556b3c9d00010b2f8909cf')

當(dāng)一個(gè)文件被插入一個(gè)特殊的鍵,“_id”,自動(dòng)添加如果文檔沒(méi)有包含一個(gè)“_id”鍵。“_id”的值必須在這個(gè)集合是唯一的。insert_one()返回InsertOneResult的一個(gè)實(shí)例。有關(guān)“_id”的更多信息,請(qǐng)參見(jiàn)_id的文檔。

插入第一個(gè)文檔后,該帖收集實(shí)際上已在服務(wù)器上創(chuàng)建。我們可以通過(guò)列出所有在我們的數(shù)據(jù)庫(kù)中收集的驗(yàn)證這一點(diǎn):

>>> db.collection_names(include_system_collections=False)

Out[6]: [u'posts']

5.2單個(gè)文檔的獲取find_one()

查詢(xún)最基本的類(lèi)型,可以在MongoDB中進(jìn)行的find_one()。該方法返回一個(gè)單一的文件匹配查詢(xún)(或無(wú),如果沒(méi)有匹配),當(dāng)你知道只有一個(gè)匹配的文件,或者只關(guān)心在第一文件匹配是非常有用的,使用find_one()來(lái)獲得職位收集的頭文件:

In [7]: posts.find_one()

Out[7]:

{u'_id': ObjectId('565583369d00010c0ad19cd6'),

u'author': u'Mike',

u'date': datetime.datetime(2015,11, 25, 9, 45, 22, 80000),

u'tags': [u'mongodb', u'python',u'pymongo'],

u'text': u'My first blog post!'}

Note:上面的結(jié)果是一個(gè)辭典匹配,先前插入的那個(gè)。返回文檔中包含一個(gè)“_id”,這是在插入自動(dòng)添加。

如果嘗試用不同的author,如“Eliot”會(huì)得到任何結(jié)果:

In [8]: posts.find_one({"author": "Eliot"})

沒(méi)有結(jié)果;

如果嘗試,“Mike”會(huì)得到如下結(jié)果:

In [9]: posts.find_one({"author": "Mike"})

Out[9]:

{u'_id': ObjectId('565583369d00010c0ad19cd6'),

u'author': u'Mike',

u'date': datetime.datetime(2015,11, 25, 9, 45, 22, 80000),

u'tags': [u'mongodb', u'python',u'pymongo'],

u'text': u'My first blog post!'}

5.3通過(guò)ObjectId查詢(xún)

我們也可以找到一個(gè)位置由它的_id,這在我們的例子中是一個(gè)的ObjectId:

In [10]: post_id

Out[10]: ObjectId('565583369d00010c0ad19cd6')

In [11]: posts.find_one({"_id": post_id})

Out[11]:

{u'_id': ObjectId('565583369d00010c0ad19cd6'),

u'author': u'Mike',

u'date': datetime.datetime(2015,11, 25, 9, 45, 22, 80000),

u'tags': [u'mongodb', u'python',u'pymongo'],

u'text': u'My first blog post!'}

注意,一個(gè)ObjectId存在不一樣的字符串表示:

In [13]: post_id_as_str = str(post_id)

posts.find_one({"_id":post_id_as_str}) #

沒(méi)有任何結(jié)果

在Web應(yīng)用程序中的一個(gè)常見(jiàn)的任務(wù)是讓從請(qǐng)求URL中的ObjectId,并找到匹配的文件。有必要在這種情況下將它傳遞到find_one()之前從字符串轉(zhuǎn)換的ObjectId:

from bson.objectid import ObjectId

# The web framework gets post_id from the URL and passes it as a string

def get(post_id):

# Convert from string toObjectId:

document =client.db.collection.find_one({'_id': ObjectId(post_id)})

5.4 批量插入(Bulk Inserts)

除了插入一個(gè)單一的文件,我們也可以執(zhí)行批量插入操作,通過(guò)傳遞列表作為第一個(gè)參數(shù)insert_many()。這將插入每個(gè)文件在列表中,只發(fā)送一個(gè)命令到服務(wù)器:

In [14]:

new_posts = [{"author": "Mike",

"text": "Anotherpost",

"tags":["bulk", "insert"],

"date":datetime.datetime(2009, 11, 12, 11, 14)},

{"author":"Eliot",

"title": "MongoDB isfun",

"text":"and pretty easy too!",

"date":datetime.datetime(2009, 11, 10, 10, 45)}]

result = posts.insert_many(new_posts)

result.inserted_ids

Out[14]:

[ObjectId('565589029d00010c0ad19cd7'), ObjectId('565589029d00010c0ad19cd8')]

Note:有幾個(gè)有趣的事情需要注意這個(gè)例子:

l從insert_many(),結(jié)果返回兩個(gè)的ObjectId,而且每一個(gè)都插入到了文件。

lnew_posts [ 1 ]都有不同的“tags”比其他位置-沒(méi)有“標(biāo)簽”欄,我們?cè)黾恿艘粋€(gè)新的類(lèi),“title”。從這可以看出MongoDB的構(gòu)架是自由化的,可以自行增加和刪減;

5.5 多文檔查詢(xún)

為了獲得更多的比一個(gè)單一的文件,因?yàn)槲覀兪褂胒ind()方法查詢(xún)的結(jié)果。find()返回游標(biāo)實(shí)例,它允許我們遍歷所有匹配的文件。例如,我們可以遍歷的數(shù)據(jù)庫(kù)收集每一份文件:

In [16]:

for post in posts.find():

print post

{u'date': datetime.datetime(2015, 11, 25, 9, 45, 22, 80000), u'text':u'My first blog post!', u'_id': ObjectId('565583369d00010c0ad19cd6'),u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}

{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Anotherpost', u'_id': ObjectId('565589029d00010c0ad19cd7'), u'author': u'Mike',u'tags': [u'bulk', u'insert']}

{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'andpretty easy too!', u'_id': ObjectId('565589029d00010c0ad19cd8'), u'author':u'Eliot', u'title': u'MongoDB is fun'}

就像我們用find_one()一樣,我們可以通過(guò)find()來(lái)限制文檔的返回結(jié)果。在這里,我們得到它的作者是“Mike”只有那些文件:

In [17]: for post in posts.find({"author":"Mike"}):

print post

{u'date':datetime.datetime(2015, 11, 25, 9, 45, 22, 80000), u'text': u'My first blogpost!', u'_id': ObjectId('565583369d00010c0ad19cd6'), 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('565589029d00010c0ad19cd7'), u'author': u'Mike', u'tags': [u'bulk',u'insert']}

5.6 范圍查詢(xún)

MongoDB的支持許多不同類(lèi)型的高級(jí)查詢(xún)。作為一個(gè)例子,執(zhí)行我們結(jié)果限制的位置早于某個(gè)日期,也由作者對(duì)結(jié)果進(jìn)行排序的查詢(xún):

In [20]:

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'andpretty easy too!', u'_id': ObjectId('565589029d00010c0ad19cd8'), u'author':u'Eliot', u'title': u'MongoDB is fun'}

{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Anotherpost', u'_id': ObjectId('565589029d00010c0ad19cd7'), u'author': u'Mike',u'tags': [u'bulk', u'insert']}

六、簡(jiǎn)單的統(tǒng)計(jì)

如果我們只是想知道有多少文件匹配,我們可以執(zhí)行查詢(xún)函數(shù)count()。得到所有集合中的文件的計(jì)數(shù):

In [18]: posts.count()

Out[18]: 3

或者那些符合特定格式的文件:

In [19]: posts.find({"author": "Mike"}).count()

Out[19]: 2

七、刪除文檔

可以使用集合的remove()方法從集合中刪除一個(gè)文檔。remove方法和find、find_one一樣,也可以使用一個(gè)字典參數(shù)來(lái)指定哪個(gè)文檔需要被刪除。比如,要?jiǎng)h除所有"author"鍵的值為"Mike"的文檔,輸入:

In [26]: posts.remove({"author": "Mike"})

Out[26]: {u'n': 4, u'ok': 1}

In [27]: for nl in posts.find():

print nl

{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'andpretty easy too!', u'_id': ObjectId('565589029d00010c0ad19cd8'), u'author':u'Eliot', u'title': u'MongoDB is fun'}

{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'andpretty easy too!', u'_id': ObjectId('56559fb89d00010d55ba1d12'), u'author':u'Eliot', u'title': u'MongoDB is fun'}

八、案例解析

8.1常見(jiàn)mongoDB函數(shù)的創(chuàng)建集成案例

源碼見(jiàn)附錄;

8.2將10條信息寫(xiě)入mongdb數(shù)據(jù)庫(kù)的案例

源碼見(jiàn)附錄

注:未經(jīng)許可不得轉(zhuǎn)載!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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