mongodb數(shù)據(jù)庫(1)

2018-02-24 15:48 更新

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

mongodb是屬于NoSql的。

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

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

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

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

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

安裝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),可以到官方網(wǎng)站下載安裝程序:http://www.mongodb.org/downloads,能滿足各種操作系統(tǒng)。

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

window平臺安裝 MongoDB

NoSQL之【MongoDB】學(xué)習(xí)(一):安裝說明

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

在Ubuntu中安裝MongoDB

在Ubuntu下進行MongoDB安裝步驟

啟動mongodb

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

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

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

> use mydb
switched to db mydb
> db
mydb

除非向這個數(shù)據(jù)庫中增加實質(zhì)性的內(nèi)容,否則它是看不到的。

> show dbs;
local   0.03125GB

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

> 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指向了數(shù)據(jù)庫mydb,books是這個數(shù)據(jù)庫里面的一個集合(類似mysql里面的表),向集合books里面插入了一個文檔(文檔對應(yīng)mysql里面的記錄)。“數(shù)據(jù)庫、集合、文檔”構(gòu)成了mongodb數(shù)據(jù)庫。

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

> show dbs
local   0.03125GB
mydb    0.0625GB

當(dāng)有了充實內(nèi)容之后,也看到剛才用到的數(shù)據(jù)庫mydb了。

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

安裝pymongo

要用python來驅(qū)動mongodb,必須要安裝驅(qū)動模塊,即pymongo,這跟操作mysql類似。安裝方法,我最推薦如下:

$ sudo pip install pymongo

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

Successfully installed pymongo
Cleaning up...

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

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

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

$ sudo pip install pymongo==2.8

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

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

>>> import pymongo

說明模塊沒有問題。

連接mongodb

既然python驅(qū)動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'

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

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

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

>>> 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ā)現(xiàn)了它:MongoClient()

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

很好。python已經(jīng)和mongodb建立了連接。

剛才已經(jīng)建立了一個數(shù)據(jù)庫mydb,并且在這個庫里面有一個集合books,于是:

>>> db = client.mydb

或者

>>> db = client['mydb']

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

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

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

>>> books = db["books"]

或者

>>> books = db.books

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

編輯

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

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

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

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

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

>>> 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()方法,它返回的是一個可迭代對象,包含著集合中所有的文檔。

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

>>> 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中,可以實現(xiàn)多條數(shù)據(jù)用一條命令插入到表里面,還記得嗎?忘了看上一節(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')]

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

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

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

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

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

對于查詢結(jié)果,還可以進行排序:

>>> 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()中的第二個參數(shù),意思是升序排列。如果按照降序,就需要將參數(shù)修改為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'}

讀者如果看到這里,請務(wù)必注意一個事情,那就是mongodb中的每個文檔,本質(zhì)上都是“鍵值對”的類字典結(jié)構(gòu)。這種結(jié)構(gòu),一經(jīng)python讀出來,就可以用字典中的各種方法來操作。與此類似的還有一個名為json的東西,可以閱讀本教程第貳季進階的第陸章模塊中的《標(biāo)準(zhǔn)庫(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中的模塊使用說明。

更新

對于已有數(shù)據(jù),進行更新,是數(shù)據(jù)庫中常用的操作。比如,要更新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)建。

關(guān)于修改器,不僅僅是這一個,還有別的呢。

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

刪除

刪除可以用remove()方法:

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

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

索引

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

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

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

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號