鍍金池/ 教程/ Python/ mongodb 數據庫 (1)
標準庫 (4)
如何成為 Python 高手
標準庫 (6)
標準庫 (3)
類(2)
Pandas 使用 (2)
xml
用 tornado 做網站 (5)
文件(1)
練習
列表(3)
從小工到專家
除法
錯誤和異常 (2)
函數(1)
用 tornado 做網站 (7)
為做網站而準備
函數練習
標準庫 (8)
Pandas 使用 (1)
回顧 list 和 str
字典(1)
用 tornado 做網站 (3)
字符串(1)
函數(2)
寫一個簡單的程序
將數據存入文件
語句(5)
SQLite 數據庫
集成開發(fā)環(huán)境(IDE)
集合(1)
類(1)
用 tornado 做網站 (6)
用 tornado 做網站 (2)
自省
語句(4)
錯誤和異常 (1)
用 tornado 做網站 (4)
集合(2)
列表(1)
標準庫 (1)
生成器
mysql 數據庫 (1)
第三方庫
實戰(zhàn)
運算符
類(3)
字典(2)
語句(1)
數和四則運算
語句(2)
文件(2)
MySQL 數據庫 (2)
電子表格
迭代器
mongodb 數據庫 (1)
特殊方法 (2)
特殊方法 (1)
字符編碼
編寫模塊
用 tornado 做網站 (1)
標準庫 (5)
函數(4)
類(5)
字符串(2)
關于 Python 的故事
函數(3)
字符串(4)
處理股票數據
常用數學函數和運算優(yōu)先級
字符串(3)
為計算做準備
多態(tài)和封裝
類(4)
迭代
語句(3)
錯誤和異常 (3)
分析 Hello
Python 安裝
標準庫 (2)
列表(2)
元組

mongodb 數據庫 (1)

MongoDB 開始火了,這是時代發(fā)展的需要。為此,本教程也要涉及到如何用 Python 來操作 mongodb。考慮到讀者對這種數據庫可能比 mysql 之類的更陌生,所以,要用多一點的篇幅稍作介紹,當然,更完備的內容還是要去閱讀專業(yè)的 mongodb 書籍。

mongodb 是屬于 NoSql 的。

NoSql,全稱是 Not Only Sql,指的是非關系型的數據庫。它是為了大規(guī)模 web 應用而生的,其特征諸如模式自由、支持簡易復制、簡單的 API、大容量數據等等。

MongoDB 是其一,選擇它,主要是因為我喜歡,否則我不會列入我的教程。數說它的特點,可能是:

  • 面向文檔存儲
  • 對任何屬性可索引
  • 復制和高可用性
  • 自動分片
  • 豐富的查詢
  • 快速就地更新

也許還能列出更多,基于它的特點,擅長領域就在于:

  • 大數據(太時髦了!以下可以都不看,就要用它了。)
  • 內容管理和交付
  • 移動和社交基礎設施
  • 用戶數據管理
  • 數據平臺

安裝 mongodb

先演示在 ubuntu 系統(tǒng)中的安裝過程:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
sudo apt-get update
sudo apt-get install mongodb-10gen

如此就安裝完畢。上述安裝流程來自:Install MongoDB

如果你用的是其它操作系統(tǒng),可以到官方網站下載安裝程序:http://www.mongodb.org/downloads,能滿足各種操作系統(tǒng)。

http://wiki.jikexueyuan.com/project/start-learning-python/images/23201.jpg" alt="" />

難免在安裝過程中遇到問題,推薦幾個資料,供參考:

window 平臺安裝 MongoDB

NoSQL 之【MongoDB】學習(一):安裝說明

MongoDB 生產環(huán)境的安裝與配置(Ubuntu)

在 Ubuntu 中安裝 MongoDB

在 Ubuntu 下進行 MongoDB 安裝步驟

啟動 mongodb

安裝完畢,就可以啟動數據庫。因為本教程不是專門講數據庫,所以,這里不設計數據庫的詳細講解,請讀者參考有關資料。下面只是建立一個簡單的庫,并且說明 mongodb 的基本要點,目的在于為后面用 Python 來操作它做個鋪墊。

執(zhí)行 mongo 啟動 shell,顯示的也是 >,有點類似 mysql 的狀態(tài)。在 shell 中,可以實現與數據庫的交互操作。

在 shell 中,有一個全局變量 db,使用哪個數據庫,那個數據庫就會被復制給這個全局變量 db,如果那個數據庫不存在,就會新建。

> use mydb
switched to db mydb
> db
mydb

除非向這個數據庫中增加實質性的內容,否則它是看不到的。

> show dbs;
local   0.03125GB

向這個數據庫增加點東西。mongodb 的基本單元是文檔,所謂文檔,就類似與 Python 中的字典,以鍵值對的方式保存數據。

> book = {"title":"from beginner to master", "author":"qiwsir", "lang":"python"}
{
    "title" : "from beginner to master",
    "author" : "qiwsir",
    "lang" : "python"
}
> db.books.insert(book)
> db.books.find()
{ "_id" : ObjectId("554f0e3cf579bc0767db9edf"), "title" : "from beginner to master", "author" : "qiwsir", "lang" : "Python" }

db 指向了數據庫 mydb,books 是這個數據庫里面的一個集合(類似 mysql 里面的表),向集合 books 里面插入了一個文檔(文檔對應 mysql 里面的記錄)。“數據庫、集合、文檔”構成了 mongodb 數據庫。

從上面操作,還發(fā)現一個有意思的地方,并沒有類似 create 之類的命令,用到數據庫,就通過 use xxx,如果不存在就建立;用到集合,就通過 db.xxx 來使用,如果沒有就建立??梢钥偨Y為“隨用隨取隨建立”。是不是簡單的有點出人意料。

> show dbs
local   0.03125GB
mydb    0.0625GB

當有了充實內容之后,也看到剛才用到的數據庫 mydb 了。

在 mongodb 的 shell 中,可以對數據進行“增刪改查”等操作。但是,我們的目的是用 Python 來操作,所以,還是把力氣放在后面用。

安裝 Pymongo

要用 Python 來驅動 mongodb,必須要安裝驅動模塊,即 Pymongo,這跟操作 mysql 類似。安裝方法,我最推薦如下:

$ sudo pip install Pymongo

如果順利,就會看到最后的提示:

Successfully installed Pymongo
Cleaning up...

如果不選擇版本,安裝的應該是最新版本的,我在本教程測試的時候,安裝的是:

>>> import Pymongo
>>> pymongo.version
'3.0.1'

這個版本在后面給我挖了一個坑。如果讀者要指定版本,比如安裝 2.8 版本的,可以:

$ sudo pip install Pymongo==2.8

如果用這個版本,我后面遇到的坑能夠避免。

安裝好之后,進入到 Python 的交互模式里面:

>>> import Pymongo

說明模塊沒有問題。

連接 mongodb

既然 Python 驅動 mongdb 的模塊 Pymongo 業(yè)已安裝完畢,接下來就是連接,也就是建立連接對象。

>>> pymongo.Connection("localhost",27017)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'Connection'

報錯!我在去年做的項目中,就是這樣做的,并且網上查看很多教程都是這么連接。

所以,讀者如果用的是舊版本的 Pymongo,比如 2.8,仍然可以使用上面的連接方法,如果是像我一樣,是用的新的(我安裝時沒有選版本),就得注意這個問題了。

經驗主義害死人。必須看看下面有哪些方法可以用:

>>> dir(pymongo)
['ALL', 'ASCENDING', 'CursorType', 'DESCENDING', 'DeleteMany', 'DeleteOne', 'GEO2D', 'GEOHAYSTACK', 'GEOSPHERE', 'HASHED', 'IndexModel', 'InsertOne', 'MAX_SUPPORTED_WIRE_VERSION', 'MIN_SUPPORTED_WIRE_VERSION', 'MongoClient', 'MongoReplicaSetClient', 'OFF', 'ReadPreference', 'ReplaceOne', 'ReturnDocument', 'SLOW_ONLY', 'TEXT', 'UpdateMany', 'UpdateOne', 'WriteConcern', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '_cmessage', 'auth', 'bulk', 'client_options', 'collection', 'command_cursor', 'common', 'cursor', 'cursor_manager', 'database', 'errors', 'get_version_string', 'has_c', 'helpers', 'ismaster', 'message', 'mongo_client', 'mongo_replica_set_client', 'monitor', 'monotonic', 'network', 'operations', 'periodic_executor', 'pool', 'read_preferences', 'response', 'results', 'server', 'server_description', 'server_selectors', 'server_type', 'settings', 'son_manipulator', 'ssl_context', 'ssl_support', 'thread_util', 'topology', 'topology_description', 'uri_parser', 'version', 'version_tuple', 'write_concern']

瞪大我的那雙渾濁迷茫布滿血絲渴望驚喜的眼睛,透過近視鏡的玻璃片,怎么也找不到 Connection() 這個方法。原來,剛剛安裝的 Pymongo 變了,“他變了”。

不過,我發(fā)現了它:MongoClient()

>>> client = pymongo.MongoClient("localhost", 27017)

很好。Python 已經和 mongodb 建立了連接。

剛才已經建立了一個數據庫 mydb,并且在這個庫里面有一個集合 books,于是:

>>> db = client.mydb

或者

>>> db = client['mydb']

獲得數據庫 mydb,并賦值給變量 db(這個變量不是 mongodb 的 shell 中的那個 db,此處的 db 就是 Python 中一個尋常的變量)。

>>> db.collection_names()
[u'system.indexes', u'books']

查看集合,發(fā)現了我們已經建立好的那個 books,于是在獲取這個集合,并賦值給一個變量 books:

>>> books = db["books"]

或者

>>> books = db.books

接下來,就可以操作這個集合中的具體內容了。

編輯

剛剛的 books 所引用的是一個 mongodb 的集合對象,它就跟前面學習過的其它對象一樣,有一些方法供我們來驅使。

>>> type(books)
<class 'pymongo.collection.Collection'>

>>> dir(books)
['_BaseObject__codec_options', '_BaseObject__read_preference', '_BaseObject__write_concern', '_Collection__create', '_Collection__create_index', '_Collection__database', '_Collection__find_and_modify', '_Collection__full_name', '_Collection__name', '__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattr__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__module__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_command', '_count', '_delete', '_insert', '_socket_for_primary_reads', '_socket_for_reads', '_socket_for_writes', '_update', 'aggregate', 'bulk_write', 'codec_options', 'count', 'create_index', 'create_indexes', 'database', 'delete_many', 'delete_one', 'distinct', 'drop', 'drop_index', 'drop_indexes', 'ensure_index', 'find', 'find_and_modify', 'find_one', 'find_one_and_delete', 'find_one_and_replace', 'find_one_and_update', 'full_name', 'group', 'index_information', 'initialize_ordered_bulk_op', 'initialize_unordered_bulk_op', 'inline_map_reduce', 'insert', 'insert_many', 'insert_one', 'list_indexes', 'map_reduce', 'name', 'next', 'options', 'parallel_scan', 'read_preference', 'reindex', 'remove', 'rename', 'replace_one', 'save', 'update', 'update_many', 'update_one', 'with_options', 'write_concern']

這么多方法不會一一介紹,只是按照“增刪改查”的常用功能,介紹幾種。讀者可以使用 help() 去查看每一種方法的使用說明。

>>> books.find_one()
{u'lang': u'Python', u'_id': ObjectId('554f0e3cf579bc0767db9edf'), u'author': u'qiwsir', u'title': u'from beginner to master'}

提醒讀者注意的是,如果你熟悉了 mongodb 的 shell 中的命令,跟 Pymongo 中的方法稍有差別,比如剛才這個,在 mongodb 的 shell 中是這樣子的:

> db.books.findOne()
{
    "_id" : ObjectId("554f0e3cf579bc0767db9edf"),
    "title" : "from beginner to master",
    "author" : "qiwsir",
    "lang" : "python"
}

請注意區(qū)分。

目前在集合 books 中,有一個文檔,還想再增加,于是插入一條:

新增和查詢

>>> b2 = {"title":"physics", "author":"Newton", "lang":"english"}
>>> books.insert(b2)
ObjectId('554f28f465db941152e6df8b')

成功地向集合中增加了一個文檔。得看看結果(我們就是充滿好奇心的小孩子,我記得女兒小時候,每個給她照相,拍了一張,她總要看一看?,F在我們似乎也是這樣,如果不看看,總覺得不放心),看看就是一種查詢。

>>> books.find().count()
2

這是查看當前集合有多少個文檔的方式,返回值為 2,則說明有兩條文檔了。還是要看看內容。

>>> books.find_one()
{u'lang': u'python', u'_id': ObjectId('554f0e3cf579bc0767db9edf'), u'author': u'qiwsir', u'title': u'from beginner to master'}

這個命令就不行了,因為它只返回第一條。必須要:

>>> for i in books.find():
...     print i
... 
{u'lang': u'Python', u'_id': ObjectId('554f0e3cf579bc0767db9edf'), u'author': u'qiwsir', u'title': u'from beginner to master'}
{u'lang': u'english', u'title': u'physics', u'_id': ObjectId('554f28f465db941152e6df8b'), u'author': u'Newton'}

在 books 引用的對象中有 find() 方法,它返回的是一個可迭代對象,包含著集合中所有的文檔。

由于文檔是鍵值對,也不一定每條文檔都要結構一樣,比如,也可以插入這樣的文檔進入集合。

>>> books.insert({"name":"Hertz"})
ObjectId('554f2b4565db941152e6df8c')
>>> for i in books.find():
...     print i
... 
{u'lang': u'Python', u'_id': ObjectId('554f0e3cf579bc0767db9edf'), u'author': u'qiwsir', u'title': u'from beginner to master'}
{u'lang': u'english', u'title': u'physics', u'_id': ObjectId('554f28f465db941152e6df8b'), u'author': u'Newton'}
{u'_id': ObjectId('554f2b4565db941152e6df8c'), u'name': u'Hertz'}

如果有多個文檔,想一下子插入到集合中(在 mysql 中,可以實現多條數據用一條命令插入到表里面,還記得嗎?忘了看上一節(jié)),可以這么做:

>>> n1 = {"title":"java", "name":"Bush"}
>>> n2 = {"title":"fortran", "name":"John Warner Backus"}
>>> n3 = {"title":"lisp", "name":"John McCarthy"}
>>> n = [n1, n2, n3]
>>> n
[{'name': 'Bush', 'title': 'java'}, {'name': 'John Warner Backus', 'title': 'fortran'}, {'name': 'John McCarthy', 'title': 'lisp'}]
>>> books.insert(n)
[ObjectId('554f30be65db941152e6df8d'), ObjectId('554f30be65db941152e6df8e'), ObjectId('554f30be65db941152e6df8f')]

這樣就完成了所謂的批量插入,查看一下文檔條數:

>>> books.find().count()
6

但是,要提醒讀者,批量插入的文檔大小是有限制的,網上有人說不要超過 20 萬條,有人說不要超過 16MB,我沒有測試過。在一般情況下,或許達不到上線,如果遇到極端情況,就請讀者在使用時多注意了。

如果要查詢,除了通過循環(huán)之外,能不能按照某個條件查呢?比如查找'name'='Bush'的文檔:

>>> books.find_one({"name":"Bush"})
{u'_id': ObjectId('554f30be65db941152e6df8d'), u'name': u'Bush', u'title': u'java'}

對于查詢結果,還可以進行排序:

>>> for i in books.find().sort("title", pymongo.ASCENDING):
...     print i
... 
{u'_id': ObjectId('554f2b4565db941152e6df8c'), u'name': u'Hertz'}
{u'_id': ObjectId('554f30be65db941152e6df8e'), u'name': u'John Warner Backus', u'title': u'fortran'}
{u'lang': u'python', u'_id': ObjectId('554f0e3cf579bc0767db9edf'), u'author': u'qiwsir', u'title': u'from beginner to master'}
{u'_id': ObjectId('554f30be65db941152e6df8d'), u'name': u'Bush', u'title': u'java'}
{u'_id': ObjectId('554f30be65db941152e6df8f'), u'name': u'John McCarthy', u'title': u'lisp'}
{u'lang': u'english', u'title': u'physics', u'_id': ObjectId('554f28f465db941152e6df8b'), u'author': u'Newton'}

這是按照"title"的值的升序排列的,注意 sort() 中的第二個參數,意思是升序排列。如果按照降序,就需要將參數修改為 Pymongo.DESCEDING,也可以指定多個排序鍵。

>>> for i in books.find().sort([("name",pymongo.ASCENDING),("name",pymongo.DESCENDING)]):
...     print i
... 
{u'_id': ObjectId('554f30be65db941152e6df8e'), u'name': u'John Warner Backus', u'title': u'fortran'}
{u'_id': ObjectId('554f30be65db941152e6df8f'), u'name': u'John McCarthy', u'title': u'lisp'}
{u'_id': ObjectId('554f2b4565db941152e6df8c'), u'name': u'Hertz'}
{u'_id': ObjectId('554f30be65db941152e6df8d'), u'name': u'Bush', u'title': u'java'}
{u'lang': u'python', u'_id': ObjectId('554f0e3cf579bc0767db9edf'), u'author': u'qiwsir', u'title': u'from beginner to master'}
{u'lang': u'english', u'title': u'physics', u'_id': ObjectId('554f28f465db941152e6df8b'), u'author': u'Newton'}

讀者如果看到這里,請務必注意一個事情,那就是 mongodb 中的每個文檔,本質上都是“鍵值對”的類字典結構。這種結構,一經 Python 讀出來,就可以用字典中的各種方法來操作。與此類似的還有一個名為 json 的東西,可以閱讀本教程第貳季進階的第陸章模塊中的《標準庫(8)。但是,如果用 Python 讀過來之后,無法直接用 json 模塊中的 json.dumps() 方法操作文檔。其中一種解決方法就是將文檔中的'_id'鍵值對刪除(例如:del doc['_id']),然后使用 json.dumps() 即可。讀者也可是使用 json_util 模塊,因為它是“Tools for using Python’s json module with BSON documents”,請閱讀http://api.mongodb.org/Python/current/api/bson/json_util.html中的模塊使用說明。

更新

對于已有數據,進行更新,是數據庫中常用的操作。比如,要更新 name 為 Hertz 那個文檔:

>>> books.update({"name":"Hertz"}, {"$set": {"title":"new physics", "author":"Hertz"}})
{u'updatedExisting': True, u'connectionId': 4, u'ok': 1.0, u'err': None, u'n': 1}
>>> books.find_one({"author":"Hertz"})
{u'title': u'new physics', u'_id': ObjectId('554f2b4565db941152e6df8c'), u'name': u'Hertz', u'author': u'Hertz'}

在更新的時候,用了一個 $set 修改器,它可以用來指定鍵值,如果鍵不存在,就會創(chuàng)建。

關于修改器,不僅僅是這一個,還有別的呢。

修改器 描述
$set 用來指定一個鍵的值。如果不存在則創(chuàng)建它
$unset 完全刪除某個鍵
$inc 增加已有鍵的值,不存在則創(chuàng)建(只能用于增加整數、長整數、雙精度浮點數)
$push 數組修改器只能操作值為數組,存在 key 在值末尾增加一個元素,不存在則創(chuàng)建一個數組

刪除

刪除可以用 remove() 方法:

>>> books.remove({"name":"Bush"})
{u'connectionId': 4, u'ok': 1.0, u'err': None, u'n': 1}
>>> books.find_one({"name":"Bush"})
>>> 

這是將那個文檔全部刪除。當然,也可以根據 mongodb 的語法規(guī)則,寫個條件,按照條件刪除。

索引

索引的目的是為了讓查詢速度更快,當然,在具體的項目開發(fā)中,要視情況而定是否建立索引。因為建立索引也是有代價的。

>>> books.create_index([("title", pymongo.DESCENDING),])
u'title_-1'

我這里僅僅是對 Pymongo 模塊做了一個非常簡單的介紹,在實際使用過程中,上面知識是很有限的,所以需要讀者根據具體應用場景再結合 mongodb 的有關知識去嘗試新的語句。


總目錄   |   上節(jié):mysql數據庫(2)   |   下節(jié):sqlite數據庫

如果你認為有必要打賞我,請通過支付寶:qiwsir@126.com,不勝感激。

上一篇:字符編碼下一篇:第三方庫