Python-MongoDB翻譯

文章首發:點點寒彬的博客

前言

都說MongoDB這個NoSql數據庫特別友好,使用起來也非常方便,今天稍微接觸了一下,發現真的是非常非常簡單,但是網上對這塊內容涉及的很少,而且很多內容都是很老的版本使用的方法,我看了一下官方API文檔中描述的內容也不多,順手翻譯一下吧,造福一下后來人。

注:我并不是逐字逐句的翻譯,在某些地方我無法精確翻譯的時候,我概括了大概的意思,有能力的可以直接看官方文檔

前提條件

首先,我們需要安裝PyMongo模塊,在PythonShell中下面的代碼能正常運行且無報錯。

>>> import pymongo

當然,你的MongoDB需要在默認地址和端口開啟,你可以按照這個方法確認你是否安裝了MongoDB:

$ mongod

建立一個MongoClient

第一步我們需要建立一個MongoClient來運行MongoDB,這個做起來非常簡單:

>>> from pymongo import MongoClient
>>> client = MongoClient()

上面的代碼會連接默認的地址和端口,我們也可以自己指定地址和端口,像下面這樣:

>>> client = MongoClient('localhost', 27017)

或者使用MongoDB的URI連接:

>>> client = MongoClient('mongodb://localhost:27017/')

獲取數據庫

一個MongoDB可以提供多個數據庫接口。當使用PyMongo的時候,你可以使用獲取屬性的方式建立MongoClient:

>>> db = client.test_database

如果你使用上面的方法無法獲取數據庫的時候,你可以使用字典的方式來獲取數據庫。

獲取連接

獲取連接的方式和獲取數據庫的方式一樣,也可以使用獲取屬性的方式:

>>> collection = db.test_collection

或者使用字典的方式:

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

注意:使用MongoDB建立連接非常容易,但是上面的所有操作都不是實實在在的操作了MongoDB,當第一次獲取數據庫和建立連接的時候,數據庫和連接會被創建。

文檔

MongoDB的數據格式存儲使用的是JSON風格,在PyMongo中,我們使用的字典類型就相當于數據。比如下面的數據就類似博客中的post信息:

>>> import datetime
>>> post = {"author": "Mike",
...         "text": "My first blog post!",
...         "tags": ["mongodb", "python", "pymongo"],
...         "date": datetime.datetime.utcnow()}

數據格式可以容納python的類型(就像datetime.datetime)

插入數據

往數據庫插入一條數據我們使用insert_one()方法:

>>> posts = db.posts
>>> post_id = posts.insert_one(post).inserted_id
>>> post_id
ObjectId('...')

當我們插入數據成功的時候,MongoDB會生成一個特殊的主鍵“_id”。這個主鍵“_id”的值是唯一的。insert_one()返回的值就是這個主鍵的值。

插入第一條數據后,數據庫、數據表和連接都建立了,我們可以查看列表中的所有信息:

>>> db.collection_names(include_system_collections=False)
[u'posts']

使用find_one()方法獲取一條記錄

在MongoDB中最基本的方法就是find_one()。這個方法返回一條符合條件的記錄(或者None)。當你知道某條信息只有一個的時候,這個方法非常有用,或者返回第一條數據,這里我們使用這個方法獲取第一條數據:

>>> posts.find_one()
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike'

結果是我們之前插入的一條字典型的數據。

注意:返回結果中的“_id”是插入數據時自動添加的。

find_one()同時也提供了精確查找的功能,下面的示例是我們定位author為Mike的代碼:

>>> posts.find_one({"author": "Mike"})
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike'

如果我們把author換成另外一個,則不會返回結果:

>>> posts.find_one({"author": "Eliot"})
>>>

使用ObjectId查詢

我們也可以用“_id”來查詢,下面是我們的示例:

>>> 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'

注意:ObjectId和轉換為字符串的ObjectId是不一樣的:

>>> post_id_as_str = str(post_id)
>>> posts.find_one({"_id": post_id_as_str}) # No result
>>>

在web應用中一個很常見的現象就是從URI中獲取ObjectId來查詢后臺記錄。在使用這個之前需要把str類型轉換成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 to ObjectId:
    document = client.db.collection.find_one({'_id': ObjectId(post_id)})

Unicode Strings注意事項

你可能會注意到我們的數據和存進去的數據有一些不一樣,比如( u’Mike’ 而不是‘Mike’)。

MongoDB是使用BSON來存儲數據。BSON是使用utf-8來編碼的。所以PyMongo存儲的str類型必須是utf-8的。(‘str’類型)也是要被支持的,因此Unicode類型(<‘unicode’類型>)需要先編碼成utf-8,我們的示例中PythonShell顯示的是u’Mike’而不是‘Mike’就是因為PyMongo解碼了BSON的string變成Python的unicode string。

大量的插入數據

為了讓查詢更有意思,我們需要插入多一些數據。能夠新增一條記錄,我們也可以做到新增多條記錄。使用insert_many()方法插入由第一條數據組成的列表,只需要往服務端發送一條命令:

>>> 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
  • new_post[1]有一個不同的地方,多了一個“tags”字段。而現在我們又多了一個字段,這就是我們說MongoDB非常schema-free(開放?)

查詢一條以上的記錄

我們使用find()方法來獲取一條以上的記錄。find()返回一組符合條件的記錄,并且允許我們通過迭代的方式獲取它們。例如,在post中我們可以迭代的獲取所有查詢的數據:

>>> 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還提供了許多種類的查詢方式。例如我們查詢數據的日期小于某一個日期,且按照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()來對author字段排序。

主鍵

增加一個主鍵能夠幫助我們快速而準確的查詢記錄,也可以使我們存儲的數據更加有用。在這個示例中,我們將會展示在一個已存在主鍵的表中新增一個主鍵:

首先,我們要新增一個主鍵:

>>> result = db.profiles.create_index([('user_id', pymongo.ASCENDING)],
...                                   unique=True)
>>> list(db.profiles.index_information())
[u'user_id_1', u'_id_']

注意,我們現在有兩個主鍵了,一個是MongoDB自帶的”_id“,另一個是我們新增的”user_id“。

現在,我們來新增一些用戶信息:

>>> user_profiles = [
...     {'user_id': 211, 'name': 'Luke'},
...     {'user_id': 212, 'name': 'Ziltoid'}]
>>> result = db.profiles.insert_many(user_profiles)

我們新增的主鍵阻止我們新增一條已存在這個主鍵的記錄。

>>> 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 }

寫在最后

官方文檔上并沒有給出刪除,修改記錄的方法,或許是我目前還沒看到吧,等看到了我會再補充上來的。文檔比較短,翻譯的過程中由于本人英語水平有限,并不能做到逐字逐句的翻譯,也無法保證完全準確,并且會有一些地方的內容念起來并不是那么的順口,但是官方文檔想表達的大概意思應該是不會錯的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容