MongoDB介紹
MongoDB是一個面向文檔的,開源數據庫程序,它平台無關。MongoDB像其他一些NoSQL數據庫(但不是全部!)使用JSON結構的文檔存儲數據。這是使得數據非常靈活,不需要的Schema。
一些比較重要的特點是:
- 支持多種標准查詢類型,比如matching()、comparison (, )或者正則表達式;
- 可以存儲幾乎任何類型的數據,無論是結構化,部分結構化,甚至是多態;
- 要擴展和處理更多查詢,只需添加更多的機器;
- 它是高度靈活和敏捷,讓您能夠快速開發應用程序;
- 作為基於文檔的數據庫意味着您可以在單個文檔中存儲有關您的模型的所有信息;
- 您可以隨時更改數據庫的Schema;
- 許多關系型數據庫的功能也可以在MongoDB使用(如索引)。
在運行方面,MongoDB中有相當多的功能在其他數據庫中是沒有的:
- 無論您需要獨立服務器還是完整的獨立服務器集群,MongoDB都可以根據需要進行擴展;
- MongoDB還通過在各個分片上自動移動數據來提供負載均衡支持;
- 它具有自動故障轉移支持,如果主服務器Down掉,新的主服務器將自動啟動並運行;
- MongoDB的管理服務(MMS)可以用於監控和備份MongoDB的基礎設施服務;
- 不像關系數據庫,由於內存映射文件,你將節省相當多的RAM。
雖然起初MongoDB似乎是解決我們許多問題的數據庫,但它不是沒有缺點的。MongoDB的一個常見缺點是缺少對ACID事務的支持,MongoDB在特定場景下支持ACID事務,但不是在所有情況。在單文檔級別,支持ACID事務(這是大多數事務發生的地方)。但是,由於MongoDB的分布式性質,不支持處理多個文檔的事務。
MongoDB還缺少對自然join查詢支持。在MongoDB看來:文檔意在包羅萬象,這意味着,一般來說,它們不需要參考其他文檔。在現實世界中,這並不總是有效的,因為我們使用的數據是關系性的。因此,許多人認為MongoDB應該被用作一個SQL數據庫的補充數據庫,但是當你使用MongoDB是,你會發現這是錯誤的。
MongoDB安裝
下載地址:http://www.mongodb.org/downloads
- /usr/local目錄下解壓 mongodb-linux-x86_64-rhel62-3.4.2.tgz
ln -s /usr/local/mongodb-linux-x86_64-rhel62-3.4.2 /usr/local/mongodb
- MongoDB 的可執行文件位於 bin 目錄下,所以可以將其添加到 PATH 路徑中
export PATH=/usr/local/mongodb/bin:$PATH
- 創建數據庫目錄
MongoDB的數據存儲在data目錄的db目錄下,但是這個目錄在安裝過程不會自動創建,所以你需要手動創建data目錄,並在data目錄中創建db目錄。
mkdir -p /data/db
備注:/data/db 是 MongoDB 默認的啟動的數據庫路徑(--dbpath)。
- 運行 MongoDB 服務
mongod --dbpath /monitor/mongodata
備注:mongod --help 幫助命令
- MongoDB后台管理 Shell
MongoDB Shell是MongoDB自帶的交互式Javascript shell,用來對MongoDB進行操作和管理的交互式環境。
mongo
備注:當你進入mongoDB后台后,它默認會鏈接到 test 文檔(數據庫)
- MongoDB web 用戶界面
MongoDB 提供了簡單的 HTTP 用戶界面。 如果你想啟用該功能,需要在啟動的時候指定參數 --rest 。
mongod --dbpath /monitor/mongodata --rest
MongoDB 的 Web 界面訪問端口比服務的端口多1000。
如果你的MongoDB運行端口使用默認的27017,你可以在端口號為28017訪問web用戶界面。
PyMongo
由MongoDB開發者發布的官方驅動程序PyMongo(https://pypi.python.org/pypi/pymongo/),這里通過一些例子介紹,但你也應該查看完整的文檔(https://api.mongodb.com/python/current/)。
1、pip方式安裝
pip install pymongo==3.4.0
2、模塊引用
import pymongo
3、建立連接
使用MongoClient對象建立連接: from pymongo import MongoClient client = MongoClient() 使用上面的代碼片段,將建立連接到默認主機(localhost)和端口(27017)。您還可以指定主機和/或使用端口: client = MongoClient('localhost', 27017) 或者使用MongoURl格式: client = MongoClient('mongodb://localhost:27017')
4、訪問數據庫
一旦你有一個連接的MongoClient實例,你可以在Mongo服務器中訪問任何數據庫。如果要訪問一個數據庫,你可以當作屬性一樣訪問: db = client.pymongo_test 或者你也可以使用字典形式的訪問: db = client['pymongo_test']
如果您的指定數據庫已創建,實際上並不重要。通過指定此數據庫名稱並將數據保存到其中,您將自動創建數據庫。
5、插入文檔
在數據庫中存儲數據,就如同調用只是兩行代碼一樣容易。第一行指定你將使用哪個集合。在MongoDB中術語中,一個集合是在數據庫中存儲在一起的一組文檔(相當於SQL的表)。集合和文檔類似於SQL表和行。第二行是使用集合插入數據insert_one()的方法:
posts = db.posts post_data = { 'title': 'Python and MongoDB', 'content': 'PyMongo is fun, you guys', 'author': 'Scott' } result = posts.insert_one(post_data) print('One post: {0}'.format(result.inserted_id))
我們甚至可以使用insert_one()同時插入很多文檔,如果你有很多的文檔添加到數據庫中,可以使用方法insert_many()。此方法接受一個list參數:
post_1 = { 'title': 'Python and MongoDB', 'content': 'PyMongo is fun, you guys', 'author': 'Scott' } post_2 = { 'title': 'Virtual Environments', 'content': 'Use virtual environments, you guys', 'author': 'Scott' } post_3 = { 'title': 'Learning Python', 'content': 'Learn Python, it is easy', 'author': 'Bill' } new_result = posts.insert_many([post_1, post_2, post_3]) print('Multiple posts: {0}'.format(new_result.inserted_ids))
看到類似輸出:
One post: 584d947dea542a13e9ec7ae6 Multiple posts: [ ObjectId('584d947dea542a13e9ec7ae7'), ObjectId('584d947dea542a13e9ec7ae8'), ObjectId('584d947dea542a13e9ec7ae9') ]
注意: 不要擔心,你和上面顯示不一樣。它們是在插入數據時,由Unix的紀元,機器標識符和其他唯一數據組成的動態標識。
6、檢索文檔
檢索文檔可以使用find_one()方法,比如要找到author為Bill的記錄:
bills_post = posts.find_one({'author': 'Bill'}) print(bills_post) 運行結果: { 'author': 'Bill', 'title': 'Learning Python', 'content': 'Learn Python, it is easy', '_id': ObjectId('584c4afdea542a766d254241') }
這篇文章的ObjectId是設置的_id,這是以后可以使用唯一標識。如果需要查詢多條記錄可以使用find()方法:
scotts_posts = posts.find({'author': 'Scott'}) print(scotts_posts) 結果: <pymongo.cursor.Cursor object at 0x109852f98>
他的主要區別在於文檔數據不是作為數組直接返回給我們。相反,我們得到一個游標對象的實例。這Cursor是一個包含相當多的輔助方法,以幫助您處理數據的迭代對象。要獲得每個文檔,只需遍歷結果:
for post in scotts_posts: print(post)
MongoEngine
雖然PyMongo是非常容易使用,總體上是一個偉大的輪子,但是許多項目使用它都可能太低水平。簡而言之,你必須編寫很多自己的代碼來持續地保存,檢索和刪除對象。PyMongo之上提供了一個更高的抽象一個庫是MongoEngine。MongoEngine是一個對象文檔映射器(ODM),它大致相當於一個基於SQL的對象關系映射器(ORM)。MongoEngine提供的抽象是基於類的,所以你創建的所有模型都是類。雖然有相當多的Python的庫可以幫助您使用MongoDB,MongoEngine是一個更好的,因為它有一個很好的組合的功能,靈活性和社區支持。
用戶指南: http://docs.mongoengine.org/guide/index.html
1、pip方式安裝
pip install mongoengine==0.10.7
2、連接
from mongoengine import * connect('mongoengine_test', host='localhost', port=27017)
備注:和pymongo不同。MongoEngine需要制定數據庫名稱。
3、定義文檔
建立文檔之前,需要定義文檔中要存放數據的字段。與許多其他ORM類似,我們將通過繼承Document類,並提供我們想要的數據類型來做到這一點:
import datetime class Post(Document): title = StringField(required=True, max_length=200) content = StringField(required=True) author = StringField(required=True, max_length=50) published = DateTimeField(default=datetime.datetime.now)
在這個簡單的模型中,我們已經告訴MongoEngine,我們的Post實例有title、content、author、published。現在Document對象可以使用該信息來驗證我們提供它的數據。
因此,如果我們試圖保存Post的中沒有title那么它會拋出一個Exception,讓我們知道。我們甚至可以進一步利用這個並添加更多的限制:
- required:設置必須;
- default:如果沒有其他值給出使用指定的默認值
- unique:確保集合中沒有其他document有此字段的值相同
- choices:確保該字段的值等於數組中的給定值之一
4、保存文檔
將文檔保存到數據庫中,我們將使用save()的方法。如果文檔中的數據庫已經存在,則所有的更改將在原子水平上對現有的文檔進行。如果它不存在,但是,那么它會被創建。
這里是創建和保存一個文檔的例子:
post_1 = Post( title='Sample Post', content='Some engaging content', author='Scott' ) post_1.save() # This will perform an insert print(post_1.title) post_1.title = 'A Better Post Title' post_1.save() # This will perform an atomic edit on "title" print(post_1.title)
調用save()的時候需要注意幾點:
- PyMongo將在您調用.save()時執行驗證,這意味着它將根據您在類中聲明的模式檢查要保存的數據,如果違反模式(或約束),則拋出異常並且不保存數據;
- 由於Mongo不支持真正的事務,因此沒有辦法像在SQL數據庫中那樣“回滾”.save()調用。
當你保存的數據沒有title時:
post_2 = Post(content='Content goes here', author='Michael') post_2.save() raise ValidationError(message, errors=errors) mongoengine.errors.ValidationError: ValidationError (Post:None) (Field is required: ['title'])
5、向對象的特性
使用MongoEngine是面向對象的,你也可以添加方法到你的子類文檔。例如下面的示例,其中函數用於修改默認查詢集(返回集合的所有對象)。通過使用它,我們可以對類應用默認過濾器,並只獲取所需的對象
class Post(Document): title = StringField() published = BooleanField() @queryset_manager def live_posts(clazz, queryset): return queryset.filter(published=True)
6、關聯其他文檔
你還可以使用ReferenceField對象來創建從一個文檔到另一個文檔的引用。MongoEngine在訪問時自動惰性處理引用。
class Author(Document): name = StringField() class Post(Document): author = ReferenceField(Author) Post.objects.first().author.name
在上面的代碼中,使用文檔”外鍵”,我們可以很容易地找到第一篇文章的作者。其實還有比這里介紹的更多的字段類(和參數),所以一定要查看文檔字段更多信息。
參考博客:https://realpython.com/blog/python/introduction-to-mongodb-and-python/