99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋(píng)果6袋
6
麥子學(xué)院

Python應(yīng)用中如何使用MongoDB?

發(fā)布時(shí)間:2017-01-01 13:50  回復(fù):0  查看:2391   最后回復(fù):2017-01-01 13:50  

Python是開(kāi)發(fā)社區(qū)中用于許多不同類型應(yīng)用的強(qiáng)大編程語(yǔ)言。很多人都知道它是可以處理幾乎任何任務(wù)的靈活語(yǔ)言。因此,在Python應(yīng)用中需要一個(gè)什么樣的與語(yǔ)言本身一樣靈活的數(shù)據(jù)庫(kù)呢?那就是NoSQL,比如MongoDB數(shù)據(jù)庫(kù)

  1SQL vs NoSQL

  如果你不是很熟悉NoSQL這個(gè)概念,MongoDB就是一個(gè)NoSQL數(shù)據(jù)庫(kù)。近幾年來(lái)它越來(lái)越受到整個(gè)行業(yè)的歡迎。NoSQL數(shù)據(jù)庫(kù)提供了一個(gè)和關(guān)系型數(shù)據(jù)庫(kù)非常不同的檢索方式和存儲(chǔ)數(shù)據(jù)功能。

  在NoSQL出現(xiàn)的幾十年來(lái),SQL數(shù)據(jù)庫(kù)是開(kāi)發(fā)者尋求構(gòu)建大型、可擴(kuò)展系統(tǒng)的唯一選擇之一。然而,越來(lái)越多的需求要求存儲(chǔ)復(fù)雜數(shù)據(jù)結(jié)構(gòu)的能力。這推動(dòng)了NoSQL數(shù)據(jù)庫(kù)的誕生,它允許開(kāi)發(fā)者存儲(chǔ)異構(gòu)和無(wú)結(jié)構(gòu)的數(shù)據(jù)。

  當(dāng)?shù)綌?shù)據(jù)庫(kù)方案選擇時(shí),大多數(shù)人都問(wèn)自己最后一個(gè)問(wèn)題,“SQLNoSQL的?。無(wú)論是SQLNoSQL都有自己的長(zhǎng)處和弱點(diǎn),你應(yīng)該選擇適合您的應(yīng)用需求中最好的之一。這里是兩者之間的一些區(qū)別:

  SQL

 ?。?span>模型是關(guān)系型的;

  .數(shù)據(jù)被存放在表中;

 ?。?span>適用于每條記錄都是相同類型并具有相同屬性的情況;

 ?。?span>存儲(chǔ)規(guī)范需要預(yù)定義結(jié)構(gòu);

 ?。?span>添加新的屬性意味著你必須改變整體架構(gòu);

 ?。瓵CID事務(wù)支持;

  NoSQL

 ?。?span>模型是非關(guān)系型的;

 ?。?span>可以存儲(chǔ)Json、鍵值對(duì)等(決定于NoSQL數(shù)據(jù)庫(kù)類型)

 ?。?span>并不是每條記錄都要有相同的結(jié)構(gòu);

 ?。?span>添加帶有新屬性的數(shù)據(jù)時(shí),不會(huì)影響其他;

 ?。?span>支持ACID事務(wù),根據(jù)使用的NoSQL的數(shù)據(jù)庫(kù)而有所不同;

  .一致性可以改變;

 ?。?span>橫向擴(kuò)展;

  在兩種類型的數(shù)據(jù)庫(kù)之間還有許多其他的區(qū)別,但上面提到的是一些更重要的區(qū)別。根據(jù)您的具體情況,使用SQL數(shù)據(jù)庫(kù)可能是首選,而在其他情況下,NoSQL的是更明顯的選擇。當(dāng)選擇一個(gè)數(shù)據(jù)庫(kù)時(shí),您應(yīng)該謹(jǐn)慎考慮每個(gè)數(shù)據(jù)庫(kù)的優(yōu)勢(shì)和劣勢(shì)。

  NoSQL的一個(gè)好處是,有許多不同類型的數(shù)據(jù)庫(kù)可供選擇,并且每個(gè)都有自己的用例:

 ?。甼ey-value存儲(chǔ): DynamoDB

  .文檔存儲(chǔ): CouchDB , MongoDB , RethinkDB

  .列存儲(chǔ): Cassandra

 ?。?span>數(shù)據(jù)結(jié)構(gòu)Redis , SSDB

  還有很多,但這些是一些更常見(jiàn)的類型。近年來(lái),SQLNoSQL數(shù)據(jù)庫(kù)甚至已經(jīng)開(kāi)始合并。例如,PostgreSQL現(xiàn)在支持存儲(chǔ)和查詢JSON數(shù)據(jù),很像MongoDB。有了這個(gè),你可以用Postgres實(shí)現(xiàn)MongoDB一樣的功能,但你仍然沒(méi)有MongoDB的其他優(yōu)勢(shì)(如橫向擴(kuò)容和簡(jiǎn)單的界面,等等)。

  2、MongoDB

  現(xiàn)在,讓我們將視線轉(zhuǎn)移到本文的重點(diǎn),并闡明的MongoDB的具體的一些情況。

  MongoDB是一個(gè)面向文檔的,開(kāi)源數(shù)據(jù)庫(kù)程序,它平臺(tái)無(wú)關(guān)。MongoDB像其他一些NoSQL數(shù)據(jù)庫(kù)(但不是全部?。┦褂?/span>JSON結(jié)構(gòu)的文檔存儲(chǔ)數(shù)據(jù)。這是使得數(shù)據(jù)非常靈活,不需要的Schema。

  一些比較重要的特點(diǎn)是:

  .支持多種標(biāo)準(zhǔn)查詢類型,比如matching()comparison (, )或者正則表達(dá)式;

  .可以存儲(chǔ)幾乎任何類型的數(shù)據(jù),無(wú)論是結(jié)構(gòu)化,部分結(jié)構(gòu)化,甚至是多態(tài);

 ?。?span>要擴(kuò)展和處理更多查詢,只需添加更多的機(jī)器;

 ?。?span>它是高度靈活和敏捷,讓您能夠快速開(kāi)發(fā)應(yīng)用程序;

  .作為基于文檔的數(shù)據(jù)庫(kù)意味著您可以在單個(gè)文檔中存儲(chǔ)有關(guān)您的模型的所有信息;

  .您可以隨時(shí)更改數(shù)據(jù)庫(kù)的Schema;

 ?。?span>許多關(guān)系型數(shù)據(jù)庫(kù)的功能也可以在MongoDB使用(如索引)。

  在運(yùn)行方面,MongoDB中有相當(dāng)多的功能在其他數(shù)據(jù)庫(kù)中是沒(méi)有的:

  .無(wú)論您需要獨(dú)立服務(wù)器還是完整的獨(dú)立服務(wù)器集群,MongoDB都可以根據(jù)需要進(jìn)行擴(kuò)展;

 ?。甅ongoDB還通過(guò)在各個(gè)分片上自動(dòng)移動(dòng)數(shù)據(jù)來(lái)提供負(fù)載均衡支持;

 ?。?span>它具有自動(dòng)故障轉(zhuǎn)移支持,如果主服務(wù)器Down掉,新的主服務(wù)器將自動(dòng)啟動(dòng)并運(yùn)行;

 ?。甅ongoDB的管理服務(wù)(MMS)可以用于監(jiān)控和備份MongoDB的基礎(chǔ)設(shè)施服務(wù);

 ?。?span>不像關(guān)系數(shù)據(jù)庫(kù),由于內(nèi)存映射文件,你將節(jié)省相當(dāng)多的RAM。

  雖然起初MongoDB似乎是解決我們?cè)S多問(wèn)題的數(shù)據(jù)庫(kù),但它不是沒(méi)有缺點(diǎn)的。MongoDB的一個(gè)常見(jiàn)缺點(diǎn)是缺少對(duì)ACID事務(wù)的支持,MongoDB在 特定場(chǎng)景下支持ACID事務(wù) ,但不是在所有情況。在單文檔級(jí)別,支持ACID事務(wù)(這是大多數(shù)事務(wù)發(fā)生的地方)。但是,由于MongoDB的分布式性質(zhì),不支持處理多個(gè)文檔的事務(wù)。

  MongoDB還缺少對(duì)自然join查詢支持。在MongoDB看來(lái):文檔意在包羅萬(wàn)象,這意味著,一般來(lái)說(shuō),它們不需要參考其他文檔。在現(xiàn)實(shí)世界中,這并不總是有效的,因?yàn)槲覀兪褂玫臄?shù)據(jù)是關(guān)系性的。因此,許多人認(rèn)為MongoDB應(yīng)該被用作一個(gè)SQL數(shù)據(jù)庫(kù)的補(bǔ)充數(shù)據(jù)庫(kù),但是當(dāng)你使用MongoDB是,你會(huì)發(fā)現(xiàn)這是錯(cuò)誤的。

  3、PyMongo

  現(xiàn)在我們已經(jīng)描述了MongoDB的是什么,讓我們來(lái)看看如何在Python中實(shí)際使用它。由MongoDB開(kāi)發(fā)者發(fā)布的官方驅(qū)動(dòng)程序 PyMongo ,這里通過(guò)一些例子介紹,但你也應(yīng)該查看 完整的文檔 ,因?yàn)槲覀儫o(wú)法面面俱到。

  當(dāng)然第一件事就是安裝,最簡(jiǎn)單的方式就是 pip 

  pip install pymongo==3.4.0

  注:有關(guān)更全面的指南,請(qǐng)查看文檔的 安裝/升級(jí) 頁(yè)面,并按照其中的步驟進(jìn)行設(shè)置

  完成設(shè)置后,啟動(dòng)的Python控制臺(tái)并運(yùn)行以下命令:

  >>> import pymongo

  如果沒(méi)有提出任何異常就說(shuō)明安裝成功了

  建立連接

  使用 MongoClient 對(duì)象建立連接:

  from pymongo import MongoClient

  client = MongoClient()

  使用上面的代碼片段,將建立連接到默認(rèn)主機(jī)(localhost)和端口(27017)。您還可以指定主機(jī)和/或使用端口:

  client = MongoClient('localhost', 27017)

  或者使用MongoURl格式:

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

  訪問(wèn)數(shù)據(jù)庫(kù)

  一旦你有一個(gè)連接的 MongoClient 實(shí)例,你可以在Mongo服務(wù)器中訪問(wèn)任何數(shù)據(jù)庫(kù)。如果要訪問(wèn)一個(gè)數(shù)據(jù)庫(kù),你可以當(dāng)作屬性一樣訪問(wèn):

  db = client.pymongo_test

  或者你也可以使用字典形式的訪問(wèn):

  db = client['pymongo_test']

  如果您的指定數(shù)據(jù)庫(kù)已創(chuàng)建,實(shí)際上并不重要。通過(guò)指定此數(shù)據(jù)庫(kù)名稱并將數(shù)據(jù)保存到其中,您將自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)。

  插入文檔

  在數(shù)據(jù)庫(kù)中存儲(chǔ)數(shù)據(jù),就如同調(diào)用只是兩行代碼一樣容易。第一行指定你將使用哪個(gè)集合。在MongoDB中術(shù)語(yǔ)中,一個(gè)集合是在數(shù)據(jù)庫(kù)中存儲(chǔ)在一起的一組文檔(相當(dāng)于SQL的表)。集合和文檔類似于SQL表和行。第二行是使用集合插入數(shù)據(jù)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()同時(shí)插入很多文檔,如果你有很多的文檔添加到數(shù)據(jù)庫(kù)中,可以使用方法insert_many()。此方法接受一個(gè)list參數(shù):

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

  你應(yīng)該看到類似輸出:

  One post: 584d947dea542a13e9ec7ae6

  Multiple posts: [

  ObjectId('584d947dea542a13e9ec7ae7'),

  ObjectId('584d947dea542a13e9ec7ae8'),

  ObjectId('584d947dea542a13e9ec7ae9')

  ]

  注意不要擔(dān)心,你和上面顯示不一樣。它們是在插入數(shù)據(jù)時(shí),由Unix的紀(jì)元,機(jī)器標(biāo)識(shí)符和其他唯一數(shù)據(jù)組成的動(dòng)態(tài)標(biāo)識(shí)。

  檢索文檔

  檢索文檔可以使用find_one()方法,比如要找到authorBill的記錄:

  bills_post = posts.find_one({'author': 'Bill'})

  print(bills_post)

  運(yùn)行結(jié)果:

  {

  'author': 'Bill',

  'title': 'Learning Python',

  'content': 'Learn Python, it is easy',

  '_id': ObjectId('584c4afdea542a766d254241')

  }

  您可能已經(jīng)注意到,這篇文章的ObjectId是設(shè)置的_id,這是以后可以使用唯一標(biāo)識(shí)。如果需要查詢多條記錄可以使用find()方法:

  scotts_posts = posts.find({'author': 'Scott'})print(scotts_posts)

  結(jié)果:

  他的主要區(qū)別在于文檔數(shù)據(jù)不是作為數(shù)組直接返回給我們。相反,我們得到一個(gè)游標(biāo)對(duì)象的實(shí)例。這Cursor是一個(gè)包含相當(dāng)多的輔助方法,以幫助您處理數(shù)據(jù)的迭代對(duì)象。要獲得每個(gè)文檔,只需遍歷結(jié)果:

  for post in scotts_posts:

  print(post)

  4、MongoEngine

  雖然PyMongo是非常容易使用,總體上是一個(gè)偉大的輪子,但是許多項(xiàng)目使用它都可能太低水平。簡(jiǎn)而言之,你必須編寫(xiě)很多自己的代碼來(lái)持續(xù)地保存,檢索和刪除對(duì)象。PyMongo之上提供了一個(gè)更高的抽象一個(gè)庫(kù)是MongoEngine。MongoEngine是一個(gè)對(duì)象文檔映射器(ODM),它大致相當(dāng)于一個(gè)基于SQL的對(duì)象關(guān)系映射器(ORM)。MongoEngine提供的抽象是基于類的,所以你創(chuàng)建的所有模型都是類。雖然有相當(dāng)多的Python的庫(kù)可以幫助您使用MongoDB,MongoEngine是一個(gè)更好的,因?yàn)樗幸粋€(gè)很好的組合的功能,靈活性和社區(qū)支持。

  使用pip安裝:

  pip install mongoengine==0.10.7

  連接:

  from mongoengine import *

  connect('mongoengine_test', host='localhost', port=27017)

  和pymongo不同。MongoEngine需要制定數(shù)據(jù)庫(kù)名稱。

  定義文檔

  建立文檔之前,需要定義文檔中要存放數(shù)據(jù)的字段。與許多其他ORM類似,我們將通過(guò)繼承Document類,并提供我們想要的數(shù)據(jù)類型來(lái)做到這一點(diǎn):

  import datetimeclass 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)

  在這個(gè)簡(jiǎn)單的模型中,我們已經(jīng)告訴MongoEngine,我們的Post實(shí)例有title、content、authorpublished?,F(xiàn)在Document對(duì)象可以使用該信息來(lái)驗(yàn)證我們提供它的數(shù)據(jù)。

  因此,如果我們?cè)噲D保存Post的中沒(méi)有title那么它會(huì)拋出一個(gè)Exception,讓我們知道。我們甚至可以進(jìn)一步利用這個(gè)并添加更多的限制:

 ?。畆equired:設(shè)置必須;

 ?。甦efault:如果沒(méi)有其他值給出使用指定的默認(rèn)值

 ?。畊nique:確保集合中沒(méi)有其他document有此字段的值相同

 ?。甤hoices:確保該字段的值等于數(shù)組中的給定值之一

  保存文檔

  將文檔保存到數(shù)據(jù)庫(kù)中,我們將使用save()的方法。如果文檔中的數(shù)據(jù)庫(kù)已經(jīng)存在,則所有的更改將在原子水平上對(duì)現(xiàn)有的文檔進(jìn)行。如果它不存在,但是,那么它會(huì)被創(chuàng)建。

  這里是創(chuàng)建和保存一個(gè)文檔的例子:

  post_1 = Post(

  title='Sample Post',

  content='Some engaging content',

  author='Scott'

  )

  post_1.save() # This will perform an insertprint(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)

  調(diào)用save()的時(shí)候需要注意幾點(diǎn):

  .PyMongo將在您調(diào)用.save()時(shí)執(zhí)行驗(yàn)證,這意味著它將根據(jù)您在類中聲明的模式檢查要保存的數(shù)據(jù),如果違反模式(或約束),則拋出異常并且不保存數(shù)據(jù);

 ?。?span>由于Mongo不支持真正的事務(wù),因此沒(méi)有辦法像在SQL數(shù)據(jù)庫(kù)中那樣回滾”.save()調(diào)用。

  當(dāng)你保存的數(shù)據(jù)沒(méi)有title時(shí):

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

  向?qū)ο蟮奶匦?/span>

  使用MongoEngine是面向?qū)ο蟮?,你也可以添加方法到你的子類文檔。例如下面的示例,其中函數(shù)用于修改默認(rèn)查詢集(返回集合的所有對(duì)象)。通過(guò)使用它,我們可以對(duì)類應(yīng)用默認(rèn)過(guò)濾器,并只獲取所需的對(duì)象

  class Post(Document):

  title = StringField()

  published = BooleanField()

  @queryset_manager

  def live_posts(clazz, queryset):

  return queryset.filter(published=True)

  關(guān)聯(lián)其他文檔

  您還可以使用ReferenceField對(duì)象來(lái)創(chuàng)建從一個(gè)文檔到另一個(gè)文檔的引用。MongoEngine在訪問(wèn)時(shí)自動(dòng)惰性處理引用。

  class Author(Document):

  name = StringField()

  class Post(Document):

  author = ReferenceField(Author)

  Post.objects.first().author.name

  從所有這些示例中,您應(yīng)該能夠看到,MongoEngine非常適合管理幾乎任何類型的應(yīng)用程序的數(shù)據(jù)庫(kù)對(duì)象。這些功能使得創(chuàng)建一個(gè)高效可擴(kuò)展程序變得非常容易。

 

來(lái)源:博客園

您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?