在Python應用中使用MongoDB

来源:http://www.cnblogs.com/jhao/archive/2016/12/28/6230512.html
-Advertisement-
Play Games

Python是開發社區中用於許多不同類型應用的強大編程語言。很多人都知道它是可以處理幾乎任何任務的靈活語言。因此,在Python應用中需要一個什麼樣的與語言本身一樣靈活的資料庫呢?那就是NoSQL,比如MongoDB。 英文原文:https://realpython.com/blog/python/ ...


Python是開發社區中用於許多不同類型應用的強大編程語言。很多人都知道它是可以處理幾乎任何任務的靈活語言。因此,在Python應用中需要一個什麼樣的與語言本身一樣靈活的資料庫呢?那就是NoSQL,比如MongoDB。

英文原文:https://realpython.com/blog/python/introduction-to-mongodb-and-python

  

1、SQL vs NoSQL

  如果你不是很熟悉NoSQL這個概念,MongoDB就是一個NoSQL資料庫。近幾年來它越來越受到整個行業的歡迎。NoSQL資料庫提供了一個和關係型資料庫非常不同的檢索方式和存儲數據功能。

  在NoSQL出現的幾十年來,SQL資料庫是開發者尋求構建大型、可擴展系統的唯一選擇之一。然而,越來越多的需求要求存儲複雜數據結構的能力。這推動了NoSQL資料庫的誕生,它允許開發者存儲異構和無結構的數據。

  當到資料庫方案選擇時,大多數人都問自己最後一個問題,“SQL或NoSQL的?”。無論是SQL和NoSQL都有自己的長處和弱點,你應該選擇適合您的應用需求中最好的之一。這裡是兩者之間的一些區別:

SQL

  • 模型是關係型的;

  • 數據被存放在表中;

  • 適用於每條記錄都是相同類型並具有相同屬性的情況;

  • 存儲規範需要預定義結構;

  • 添加新的屬性意味著你必須改變整體架構;

  • ACID事務支持;

NoSQL

  • 模型是非關係型的;

  • 可以存儲Json、鍵值對等(決定於NoSQL資料庫類型);

  • 並不是每條記錄都要有相同的結構;

  • 添加帶有新屬性的數據時,不會影響其他;

  • 支持ACID事務,根據使用的NoSQL的資料庫而有所不同;

  • 一致性可以改變;

  • 橫向擴展;

  在兩種類型的資料庫之間還有許多其他的區別,但上面提到的是一些更重要的區別。根據您的具體情況,使用SQL資料庫可能是首選,而在其他情況下,NoSQL的是更明顯的選擇。當選擇一個資料庫時,您應該謹慎考慮每個資料庫的優勢和劣勢。

  NoSQL的一個好處是,有許多不同類型的資料庫可供選擇,並且每個都有自己的用例:

  還有很多,但這些是一些更常見的類型。近年來,SQL和NoSQL資料庫甚至已經開始合併。例如,PostgreSQL現在支持存儲和查詢JSON數據,很像MongoDB。有了這個,你可以用Postgres實現MongoDB一樣的功能,但你仍然沒有MongoDB的其他優勢(如橫向擴容和簡單的界面,等等)。

2、MongoDB

  現在,讓我們將視線轉移到本文的重點,並闡明的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是,你會發現這是錯誤的。

3、PyMongo

  現在我們已經描述了MongoDB的是什麼,讓我們來看看如何在Python中實際使用它。由MongoDB開發者發佈的官方驅動程式PyMongo,這裡通過一些例子介紹,但你也應該查看完整的文檔,因為我們無法面面俱到。

  當然第一件事就是安裝,最簡單的方式就是pip

pip install pymongo==3.4.0

註:有關更全面的指南,請查看文檔的安裝/升級頁面,並按照其中的步驟進行設置

  完成設置後,啟動的Python控制台並運行以下命令:

>>> import pymongo

  如果沒有提出任何異常就說明安裝成功了

建立連接

  使用MongoClient對象建立連接:

from pymongo import MongoClient
client = MongoClient()

  使用上面的代碼片段,將建立連接到預設主機(localhost)和埠(27017)。您還可以指定主機和/或使用埠:

client = MongoClient('localhost', 27017)

  或者使用MongoURl格式:

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

訪問資料庫

  一旦你有一個連接的MongoClient實例,你可以在Mongo伺服器中訪問任何資料庫。如果要訪問一個資料庫,你可以當作屬性一樣訪問:

db = client.pymongo_test

  或者你也可以使用字典形式的訪問:

db = client['pymongo_test']

  如果您的指定資料庫已創建,實際上並不重要。通過指定此資料庫名稱並將數據保存到其中,您將自動創建資料庫。

插入文檔

  在資料庫中存儲數據,就如同調用只是兩行代碼一樣容易。第一行指定你將使用哪個集合。在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的紀元,機器標識符和其他唯一數據組成的動態標識。

檢索文檔

  檢索文檔可以使用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)

4、MongoEngine

  雖然PyMongo是非常容易使用,總體上是一個偉大的輪子,但是許多項目使用它都可能太低水平。簡而言之,你必須編寫很多自己的代碼來持續地保存,檢索和刪除對象。PyMongo之上提供了一個更高的抽象一個庫是MongoEngine。MongoEngine是一個對象文檔映射器(ODM),它大致相當於一個基於SQL的對象關係映射器(ORM)。MongoEngine提供的抽象是基於類的,所以你創建的所有模型都是類。雖然有相當多的Python的庫可以幫助您使用MongoDB,MongoEngine是一個更好的,因為它有一個很好的組合的功能,靈活性和社區支持。

  使用pip安裝:

pip install mongoengine==0.10.7

  連接:

from mongoengine import *
connect('mongoengine_test', host='localhost', port=27017)

  
  和pymongo不同。MongoEngine需要制定資料庫名稱。

定義文檔

  建立文檔之前,需要定義文檔中要存放數據的欄位。與許多其他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:確保該欄位的值等於數組中的給定值之一

保存文檔

  將文檔保存到資料庫中,我們將使用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'])

向對象的特性

  使用MongoEngine是面向對象的,你也可以添加方法到你的子類文檔。例如下麵的示例,其中函數用於修改預設查詢集(返回集合的所有對象)。通過使用它,我們可以對類應用預設過濾器,並只獲取所需的對象

class Post(Document):
    title = StringField()
    published = BooleanField()

    @queryset_manager
    def live_posts(clazz, queryset):
        return queryset.filter(published=True)

關聯其他文檔

  您還可以使用ReferenceField對象來創建從一個文檔到另一個文檔的引用。MongoEngine在訪問時自動惰性處理引用。

class Author(Document):
    name = StringField()

class Post(Document):
    author = ReferenceField(Author)

Post.objects.first().author.name

  在上面的代碼中,使用文檔”外鍵”,我們可以很容易地找到第一篇文章的作者。其實還有比這裡介紹的更多的欄位類(和參數),所以一定要查看文檔欄位更多信息。
  
從所有這些示例中,您應該能夠看到,MongoEngine非常適合管理幾乎任何類型的應用程式的資料庫對象。這些功能使得創建一個高效可擴展程式變得非常容易。如果你正在尋找更多關於MongoEngine的幫助,請務必查閱他們的用戶指南


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 關於java,作為一個初學者,作為一個即將跨入其中的鑽研者,我覺得我很必要好好地升入其中認真學習每一個環節 ...
  • 類 介面 成員變數,成員方法 類 介面 成員變數,成員方法 靜態內部不能有對外調用,成員獨立於該類的任何實例對象。 類變數是全局變數 類方法是全局方法。在其中不能使用this,super.不能創建內部類實例 類 介面 成員變數,成員方法 沒有子類的類 不能改變變數的值,不能改變值得欄位 不能被覆蓋的 ...
  • 最近在讀<Node入門經典>, 之前沒有做筆記, 今天開始把看過自己又寫了的代碼放這裡以免忘記. express var express = require('express') var app = express() app.get('/', function (req, res) { res.s ...
  • 浮點數值不適用於禁止出現舍入誤差的金融計算中。例如,命令System.out.println(2.0-1.1)將列印出0.8999999999999999999999999,而不是人們想象的0.9。其主要原因是浮點數值採用二進位系統表示,而在二進位系統中無法精確的表示分數1/10。這就好像十進位無法 ...
  • 最近裝了python和PyCharm開發環境,但是在安裝numpy和matplotlib等包時出現了問題,現總結一下在windows平臺下的安裝方法。 由於現在找不到了工具包新版本的exe文件,所以採用了whl格式文件的安裝。本人事先安裝了python3.5.2,電腦是32位。 1、先安裝wheel ...
  • 模板方法模式由兩個角色組成:父類角色,子類角色。 父類角色:提供模板。 子類角色:為父類模板提供實現。 類圖: JAVA代碼: AbstractClass.java ConcreteClass.java Test.java 總結:模板方法模式,定義一個操作中的演算法骨架,而將一些步驟延遲到子類中去實現 ...
  • 1 .100以內的奇數和偶數 1 .100以內的奇數和偶數 var js = ""; var os = ""; for(var i=1;i<100;i++) { if(i%2 == 0) { os = os+""+i; } else { js = js+""+i; } } alert(os); al ...
  • os.name 輸出字元串指示正在使用的平臺。如果是window 則用'nt'表示,對於Linux/Unix用戶,它是'posix'。 os.getcwd() 函數得到當前Python腳本工作的目錄路徑。 os.listdir('path') 返回指定目錄下的所有文件和目錄名。 os.listdir ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...