pymongo的官方文檔:
http://api.mongodb.org/python/current/#
pymongo的API:
http://api.mongodb.org/python/current/api/index.html
使用SSL加密:
http://api.mongodb.org/python/current/examples/tls.html
安裝
生產(chǎn)系統(tǒng):Ubuntu 14.04 LTS
目標(biāo)環(huán)境:python3.4 + MongoDB3.2 + pymongo3.2
注:注意查看官網(wǎng)的版本兼容性,里面提到pymongo3.2是可以支持MongoDB3.2的,而python3.4是支持pymongo3.0的。并沒(méi)有提及python3.4支持pymongo3.2,所以這樣的目標(biāo)環(huán)境是否兼容,我先試試。(這樣做的原因是,只有pymongo3.2支持MongoDB3.2啊)
安裝流程大致如下:
1)主要是安裝python pip,這是一款管理package的工具,類(lèi)似于easy_install。python3一般是已安裝,另外一個(gè)是編譯需要的軟件包。
sudo apt-get install python3-pip python3-dev build-essential
2)使用pip工具來(lái)安裝pymongo3.2軟件包,注意看是否在python3.4文件夾下的文件創(chuàng)建是否成功。
sudo python3 -m pip install pymongo==3.2
3)測(cè)試是否安裝成功:
xxx@machine:~$ python3
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>import pymongo
>>>
沒(méi)有顯示任何的東西,表示成功了,否則會(huì)出現(xiàn)一堆東西,一般就是沒(méi)有安裝成功。
連接mongod實(shí)例
先連接已經(jīng)開(kāi)啟的mongod實(shí)例:
>>> from pymongo import MongoClient
>>> client = MongoClient() //會(huì)按默認(rèn)來(lái)連接本地的mongod實(shí)例test(默認(rèn)創(chuàng)建的那個(gè))
指定要連接的mongod實(shí)例:
>>> client = MongoClient('localhost', 27017)
也可以用uri的方式連接(推薦):
>>> client = MongoClient('mongodb://localhost:27017/')
連接database
正常情況下,pymongo driver中的一些保留的特殊符號(hào)在使用時(shí)要小心,可能會(huì)導(dǎo)致工作無(wú)效,而python是不會(huì)報(bào)錯(cuò)的,可能會(huì)在你使用的時(shí)候才報(bào)錯(cuò)。
1)一個(gè)實(shí)例中一般有多個(gè)database,先連上自動(dòng)創(chuàng)建的那個(gè):
>>> db = client.local
另一種連接方式:
>>> db = client['local']
2)獲取db中的某個(gè)集合:
>>> collection = db.test_collection
另一種方式:
>>> collection = db['startup_log']
文檔
在MongoDB中,數(shù)據(jù)被表示成JSON-style的文檔,同時(shí)也是這樣存儲(chǔ)的(BSON)。而在pymongo中是用dict來(lái)表示的數(shù)據(jù)庫(kù)中的文檔,就像下面這樣:
>>> import datetime
>>> post = {"author": "Mike",
... "text": "My first blog post!",
... "tags": ["mongodb", "python", "pymongo"],
... "date": datetime.datetime.utcnow()}
datetime.datetime是python中具有的類(lèi)型,會(huì)被轉(zhuǎn)成合適的BSON類(lèi)型。
插入一個(gè)文檔可以是下面這樣:
>>> posts = db.posts
>>> post_id = posts.insert_one(post).inserted_id
>>> post_id
ObjectId('...')
若沒(méi)有指定id鍵,那么_id鍵還是會(huì)自動(dòng)創(chuàng)建的。如果成功了,還會(huì)返回其ObjId,可以用來(lái)唯一性的查詢(xún)。在python中,插入操作已經(jīng)完成了,但是server不一定會(huì)完成,此時(shí)可以通過(guò)列出所有的集合,驗(yàn)證一下是否真的存在這個(gè)collection:
>>> db.collection_names(include_system_collections=False)
[u'posts']
操作
搜索單個(gè)文檔的find_one()操作是比較常用的,如果搜到了就返回其中一個(gè),否則就空。就像下面這樣:
>>> posts.find_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']}
這里沒(méi)有指定條件,那么應(yīng)該會(huì)隨便返回一個(gè)文檔(對(duì)客戶(hù)端來(lái)講,是隨機(jī)的)。上面插入成功的post_id就可以拿來(lái)查詢(xún)插入的那個(gè)文檔:
>>> 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']}
要注意,ObjId并不是個(gè)字符串,因?yàn)樗趐y中已經(jīng)是個(gè)對(duì)象了,所以像下面這樣的操作是不可行的:
>>> post_id_as_str = str(post_id)
>>> posts.find_one({"_id": post_id_as_str}) # No result
>>>
使用ObjId來(lái)查詢(xún)文檔可以參考 When I query for a document by ObjectId in my web application I get no result。
批量操作(bulk)
在單獨(dú)插入的時(shí)候,我們使用的是dict來(lái)充當(dāng)一個(gè)文檔,那么批量的文檔,也就可以用list來(lái)裝dict啦??梢钥吹?,insert_many()插入成功之后返回了一個(gè)list,里面裝了很多的ObjId:
>>> 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('...')]
那么批量查詢(xún)呢?在MongoDB中的批量查詢(xún)返回的是cursor,通過(guò)迭代可以取出其中的所有文檔。這種操作就跟python中的iterable的類(lèi)型差不多,所以一般批量查詢(xún)是這樣的:
>>> 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'}
許多的操作和mongo shell中的操作是很相似的,比如:
>>> posts.find({"author": "Mike"}).count()
2
范圍的查詢(xún)可以直接使用操作符,只不過(guò)需要加上雙引號(hào),不然python可能認(rèn)不出來(lái):
>>> 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']}
關(guān)于Unicode string
上面使用find_one()操作查詢(xún)到的很多都是帶個(gè)u
在前面,這是因?yàn)镸ongoDB和py的字符串的編碼不一樣。BSON字符串使用utf-8編碼,而py使用的是Unicode編碼,所以一般數(shù)據(jù)庫(kù)的字符串相關(guān)的操作都需要進(jìn)行編碼。具體可以參考You can read more about Python unicode strings here。
關(guān)于索引(index)
對(duì)集合創(chuàng)建索引,防止重復(fù)user_id的存在:
>>> result = db.profiles.create_index([('user_id', pymongo.ASCENDING)],
... unique=True)
>>> list(db.profiles.index_information())
[u'user_id_1', u'_id_']
看看報(bào)錯(cuò)時(shí)的樣子吧:
>>> new_profile = {'user_id': 213, 'name': 'Drew'}
>>> duplicate_profile = {'user_id': 212, 'name': 'Tommy'}
>>> result = db.profiles.insert_one(new_profile) # This is fine.
>>> result = db.profiles.insert_one(duplicate_profile)
Traceback (most recent call last):
pymongo.errors.DuplicateKeyError: E11000 duplicate key error index: test_database.profiles.$user_id_1 dup key: { : 212 }