MongoDB與Redis(從入門到商業(yè)實戰(zhàn))_第1頁
MongoDB與Redis(從入門到商業(yè)實戰(zhàn))_第2頁
MongoDB與Redis(從入門到商業(yè)實戰(zhàn))_第3頁
MongoDB與Redis(從入門到商業(yè)實戰(zhàn))_第4頁
MongoDB與Redis(從入門到商業(yè)實戰(zhàn))_第5頁
已閱讀5頁,還剩331頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

MongoDB與Redis從入門到商業(yè)實戰(zhàn)目錄\h第1篇基礎(chǔ)知識\h第1章進入MongoDB與Redis的世界\h1.1非關(guān)系型數(shù)據(jù)庫的產(chǎn)生背景與分類\h1.1.1關(guān)系型數(shù)據(jù)庫遇到的問題\h1.1.2非關(guān)系型數(shù)據(jù)庫的分類及特點\h1.2MongoDB與Redis可以做什么\h1.2.1MongoDB適合做什么\h1.2.2Redis適合做什么\h1.3如何學(xué)習(xí)MongoDB和Redis\h1.3.1項目驅(qū)動,先用再學(xué)\h1.3.2系統(tǒng)梳理,由點到面\h1.3.3分清主次,不要在無謂的操作中浪費時間\h1.3.4在不同領(lǐng)域中嘗試\h1.4如何使用本書\h1.4.1本書的產(chǎn)品定位\h1.4.2本書適用的讀者群體\h1.4.3如何利用本書實例進行練習(xí)\h第2章數(shù)據(jù)存儲方式的演進\h2.1從文件到MongoDB數(shù)據(jù)庫\h2.1.1使用文件保存數(shù)據(jù)\h2.1.2使用MongoDB保存數(shù)據(jù)\h2.2從隊列Queue到Redis\h2.2.1了解“生產(chǎn)者/消費者”模型\h2.2.2實例1:使用Python實現(xiàn)隊列\(zhòng)h2.2.3Python的Queue及其缺陷\h2.2.4實例2:使用Redis替代Queue\h本章小結(jié)\h第2篇快速入門\h第3章MongoDB快速入門\h3.1MongoDB和SQL術(shù)語對比\h3.2安裝MongoDB\h3.2.1在Windows中安裝\h3.2.2在Linux中安裝\h3.2.3在macOS中安裝\h3.3MongoDB的圖形化管理軟件——Robo3T\h3.3.1安裝\h3.3.2認(rèn)識Robo3T的界面\h3.4MongoDB的基本操作\h3.4.1實例3:創(chuàng)建數(shù)據(jù)庫與集合,寫入數(shù)據(jù)\h3.4.2實例4:查詢數(shù)據(jù)\h3.4.3實例5:修改數(shù)據(jù)\h3.4.4實例6:刪除數(shù)據(jù)\h3.4.5實例7:數(shù)據(jù)去重\h3.5使用Python操作MongoDB\h3.5.1連接數(shù)據(jù)庫\h3.5.2MongoDB命令在Python中的對應(yīng)方法\h3.5.3實例8:插入數(shù)據(jù)到MongoDB\h3.5.4實例9:從MongoDB中查詢數(shù)據(jù)\h3.5.5實例10:更新/刪除MongoDB中的數(shù)據(jù)\h3.6MongoDB與Python不通用的操作\h本章小結(jié)\h第4章實例11:用MongoDB開發(fā)員工信息管理系統(tǒng)\h4.1了解實例最終目標(biāo)\h4.2準(zhǔn)備工作\h4.2.1了解文件結(jié)構(gòu)\h4.2.2搭建項目運行環(huán)境\h4.2.3啟動項目\h4.3項目開發(fā)過程\h4.3.1生成初始數(shù)據(jù)\h4.3.2實現(xiàn)“查詢數(shù)據(jù)”功能\h4.3.3實現(xiàn)“添加數(shù)據(jù)”功能\h4.3.4實現(xiàn)“更新數(shù)據(jù)”功能\h4.3.5實現(xiàn)“刪除數(shù)據(jù)”功能\h本章小結(jié)\h第5章Redis快速入門\h5.1安裝Redis\h5.1.1在Windows中安裝Redis\h5.1.2在Linux中安裝Redis\h5.1.3在macOS中安裝Redis\h5.1.4在線測試環(huán)境\h5.2字符串的創(chuàng)建、查詢和修改\h5.2.1使用redis-cli實現(xiàn)\h5.2.2使用Python實現(xiàn)\h5.2.3字符串的應(yīng)用\h5.3列表的創(chuàng)建、查詢和修改\h5.3.1使用redis-cli實現(xiàn)\h5.3.2使用Python實現(xiàn)\h5.3.3列表的應(yīng)用\h5.4集合的創(chuàng)建和修改\h5.4.1使用redis-cli實現(xiàn)\h5.4.2使用Python實現(xiàn)\h5.4.3集合的應(yīng)用\h本章小結(jié)\h第6章實例12:用Redis開發(fā)一個聊天室網(wǎng)站\h6.1了解實例的最終目標(biāo)\h6.2準(zhǔn)備工作\h6.2.1了解文件結(jié)構(gòu)\h6.2.2搭建項目運行環(huán)境\h6.3項目開發(fā)過程\h6.3.1實現(xiàn)登錄功能1:創(chuàng)建Redis的連接實例\h6.3.2實現(xiàn)登錄功能2:實現(xiàn)“檢查昵稱是否重復(fù)”功能\h6.3.3實現(xiàn)登錄功能3:實現(xiàn)“設(shè)置和獲取Token”功能\h6.3.4實現(xiàn)聊天室頁面1:實現(xiàn)“獲取聊天消息”功能\h6.3.5實現(xiàn)聊天室頁面2:實現(xiàn)“發(fā)送新信息”功能\h6.3.6實現(xiàn)聊天室頁面3:設(shè)定“刷屏檢查字符串”\h6.3.7實現(xiàn)聊天室頁面4:讀取刷屏限制的剩余時間\h本章小結(jié)\h第3篇高級應(yīng)用\h第7章MongoDB的高級語法\h7.1AND和OR操作\h7.1.1實例13:查詢同時符合兩個條件的人(AND操作)\h7.1.2實例14:查詢只符合其中任一條件的人(OR操作)\h7.1.3實例15:用Python實現(xiàn)MongoDB的AND與OR操作\h7.2查詢子文檔或數(shù)組中的數(shù)據(jù)\h7.2.1認(rèn)識嵌入式文檔\h7.2.2實例16:嵌入式文檔的應(yīng)用\h7.2.3認(rèn)識數(shù)組字段\h7.2.4實例17:數(shù)組應(yīng)用——查詢數(shù)組包含與不包含“××”的數(shù)據(jù)\h7.2.5實例18:數(shù)組應(yīng)用——根據(jù)數(shù)組長度查詢數(shù)據(jù)\h7.2.6實例19:數(shù)組應(yīng)用——根據(jù)索引查詢數(shù)據(jù)\h7.2.7Python操作嵌入式文檔與數(shù)組字段\h7.3MongoDB的聚合查詢\h7.3.1聚合的基本語法\h7.3.2實例20:篩選數(shù)據(jù)\h7.3.3實例21:篩選與修改字段\h7.3.4實例22:分組操作\h7.3.5實例23:拆分?jǐn)?shù)組\h7.3.6實例24:聯(lián)集合查詢\h7.3.7實例25:使用Python執(zhí)行聚合操作\h本章小結(jié)\h第8章MongoDB的優(yōu)化和安全建議\h8.1提高MongoDB讀寫性能\h8.1.1實例26:“批量插入”與“逐條插入”數(shù)據(jù),比較性能差異\h8.1.2實例27:“插入”與“更新”數(shù)據(jù),比較性能差異\h8.1.3實例28:使用“索引”提高查詢速度\h8.1.4實例29:引入Redis,以降低MongoDB的讀取頻率\h8.1.5實例30:增添適當(dāng)冗余信息,以提高查詢速度\h8.2提高MongoDB的安全性\h8.2.1配置權(quán)限管理機制\h8.2.2開放外網(wǎng)訪問\h本章小結(jié)\h第9章Redis的高級數(shù)據(jù)結(jié)構(gòu)\h9.1哈希表的功能和應(yīng)用\h9.1.1實例31:使用Redis記錄用戶在線狀態(tài)\h9.1.2實例32:使用Python向哈希表中添加數(shù)據(jù)\h9.1.3實例33:使用Python從哈希表中讀取數(shù)據(jù)\h9.1.4實例34:使用Python判斷哈希表中是否存在某字段,并獲取字段數(shù)量\h9.1.5實例35:在Redis交互環(huán)境redis-cli中讀/寫哈希表\h9.2發(fā)布消息/訂閱頻道\h9.2.1實例36:實現(xiàn)一對多的消息發(fā)布\h9.2.2實例37:在Python中發(fā)布消息/訂閱頻道\h9.2.3實例38:在redis-cli中發(fā)布消息/訂閱頻道\h9.3有序集合\h9.3.1實例39:實現(xiàn)排行榜功能\h9.3.2實例40:使用Python讀寫有序集合\h9.3.3實例41:在Redis交互環(huán)境redis-cli中使用有序集合\h9.4Redis的安全管理\h9.4.1實例42:設(shè)置密碼并開放外網(wǎng)訪問\h9.4.2禁用危險命令\h本章小結(jié)\h第4篇商業(yè)實戰(zhàn)\h第10章實例43:搭建一個類似“知乎”的問答網(wǎng)站\h10.1了解實例的最終目標(biāo)\h10.2準(zhǔn)備工作\h10.2.1了解文件結(jié)構(gòu)\h10.2.2搭建實例運行環(huán)境\h10.2.3運行項目\h10.3項目開發(fā)過程\h10.3.1生成初始數(shù)據(jù)\h10.3.2實現(xiàn)“查詢問題列表”功能\h10.3.3實現(xiàn)“查詢回答”功能\h10.3.4實現(xiàn)“提問與回答”功能\h10.3.5實現(xiàn)“點贊”與“點踩”功能\h本章小結(jié)\h第11章實例44:使用Redis存儲網(wǎng)站會話(接第10章實例)\h11.1了解實例的最終目標(biāo)\h11.1.1注冊賬號\h11.1.2登錄后回答問題\h11.1.3修改回答\h11.1.4用戶回答同一個問題的次數(shù)\h11.1.5修改提問\h11.2準(zhǔn)備工作\h11.2.1了解文件結(jié)構(gòu)\h11.2.2搭建項目運行環(huán)境\h11.2.3運行實例\h11.3開發(fā)過程\h11.3.1會話管理的基本原理\h11.3.2保存與讀取用戶信息\h11.3.3更新問題和回答\h11.3.4檢查用戶名是否已經(jīng)注冊\h11.3.5在Redis中儲存與刪除Session\h11.3.6從Redis中獲取Session\h11.3.7記錄和檢查“用戶回答是否回答了某個問題”\h本章小結(jié)\h第12章實例45:大規(guī)模驗重和問答排序(接第11章實例)\h12.1了解實例的最終目標(biāo)\h12.1.1賬號驗重功能\h12.1.2動態(tài)排序功能\h12.1.3注銷登錄功能\h12.2.4翻頁功能\h12.2準(zhǔn)備工作\h12.2.1了解文件結(jié)構(gòu)\h12.2.2搭建項目運行環(huán)境\h12.2.3運行項目\h12.3開發(fā)過程\h12.3.1了解“布隆過濾器”的基本原理\h12.3.2使用“布隆過濾器”對注冊用戶進行驗重\h12.3.3讓“問題”與“回答”根據(jù)點贊數(shù)動態(tài)排序\h本章小結(jié)\h第13章重構(gòu)和優(yōu)化\h13.1劃分代碼層次\h13.1.1尋找問題\h13.1.2如何重構(gòu)\h13.2MongoDB的常見陷阱\h13.2.1默認(rèn)超時時間\h13.2.2硬盤空間的使用\h13.3使用Redis的注意事項\h13.3.1“多Redis實例”與“單Redis實例多數(shù)據(jù)庫”的差異\h13.3.2盡可能為每個Key設(shè)置過期時間\h本章小結(jié)\h第1篇基礎(chǔ)知識隨著大數(shù)據(jù)時代的到來,數(shù)據(jù)急速增長,導(dǎo)致關(guān)系型數(shù)據(jù)庫(SQL)越來越不夠用。高性能、可擴展的數(shù)據(jù)庫變得越來越重要起來。在這樣的場景下,非關(guān)系型數(shù)據(jù)庫(NoSQL)應(yīng)運而生。這里的“NoSQL”不是“NoSQL(不是SQL)”,而是“NotonlySQL(不僅是SQL)”的簡稱。第1章主要介紹數(shù)據(jù)庫的產(chǎn)生背景和功能,以及如何學(xué)習(xí)它們。第2章通過實例介紹MongoDB與Redis存在的必要性。\h第1章進入MongoDB與Redis的世界非關(guān)系型數(shù)據(jù)庫在如今的大數(shù)據(jù)環(huán)境下越來越受到重用。相比傳統(tǒng)的關(guān)系型數(shù)據(jù)庫,非關(guān)系型數(shù)據(jù)庫在越來越多的使用場景下極大地提升了生產(chǎn)力。非關(guān)系型數(shù)據(jù)庫的佼佼者——文檔型數(shù)據(jù)庫MongoDB與鍵值數(shù)據(jù)庫Redis,是這本書的兩個主角。\h1.1非關(guān)系型數(shù)據(jù)庫的產(chǎn)生背景與分類\h1.1.1關(guān)系型數(shù)據(jù)庫遇到的問題2008年左右,網(wǎng)站、論壇、社交網(wǎng)絡(luò)開始高速發(fā)展,關(guān)系型數(shù)據(jù)庫的地位受到了很大的挑戰(zhàn)。關(guān)系型數(shù)據(jù)庫的以下問題逐漸凸顯:●難以應(yīng)付每秒上萬次的高并發(fā)數(shù)據(jù)寫入?!癫樵兩蟽|量級數(shù)據(jù)的速度極其緩慢。●分庫、分表形成的子庫到達一定規(guī)模后難以進一步擴展?!穹謳?、分表的規(guī)則可能會因為需求變更而發(fā)生變更?!裥薷谋斫Y(jié)構(gòu)困難。在很多互聯(lián)網(wǎng)應(yīng)用場景下,對數(shù)據(jù)聯(lián)表的查詢需求不是那么強烈,也并不需要在數(shù)據(jù)寫入后立刻讀取,但對數(shù)據(jù)的讀取和并發(fā)寫入速度有非常高的要求。在這樣的情況下,非關(guān)系型數(shù)據(jù)庫得到高速的發(fā)展。2009年,分布式文檔型數(shù)據(jù)庫MongoDB引發(fā)了一場去SQL的浪潮。\h1.1.2非關(guān)系型數(shù)據(jù)庫的分類及特點非關(guān)系型數(shù)據(jù)庫主要分為以下幾類。1.鍵值數(shù)據(jù)庫主要代表是Redis、Flare。這類數(shù)據(jù)庫具有極高的讀寫性能,用于處理大量數(shù)據(jù)的高訪問負(fù)載比較合適。2.文檔型數(shù)據(jù)庫主要代表是MongoDB、CouchDB。這類數(shù)據(jù)庫滿足了海量數(shù)據(jù)的存儲和訪問需求,同時對字段要求不嚴(yán)格,可以隨意地增加、刪除、修改字段,且不需要預(yù)先定義表結(jié)構(gòu),所以適用于各種網(wǎng)絡(luò)應(yīng)用。3.列存儲數(shù)據(jù)庫主要代表是Cassandra、Hbase。這類數(shù)據(jù)庫查找速度快,可擴展性強,適合用作分布式文件存儲系統(tǒng)。4.圖數(shù)據(jù)庫主要代表是InfoGrid、Neo4J。這類數(shù)據(jù)庫利用“圖結(jié)構(gòu)”的相關(guān)算法,適合用于構(gòu)建社交網(wǎng)絡(luò)和推薦系統(tǒng)的關(guān)系圖譜。\h1.2MongoDB與Redis可以做什么\h1.2.1MongoDB適合做什么MongoDB適合儲存大量關(guān)聯(lián)性不強的數(shù)據(jù)。MongoDB中的數(shù)據(jù)以“庫”—“集合”—“文檔”—“字段”結(jié)構(gòu)進行儲存。這種結(jié)構(gòu)咋看和傳統(tǒng)關(guān)系型數(shù)據(jù)庫的“庫”—“表”—“行”—“列”結(jié)構(gòu)非常像。但是,MongoDB不需要預(yù)先定義表結(jié)構(gòu),數(shù)據(jù)的字段可以任意變動,并發(fā)寫入速度也遠(yuǎn)遠(yuǎn)超過傳統(tǒng)關(guān)系型數(shù)據(jù)庫。\h1.2.2Redis適合做什么Redis有多種數(shù)據(jù)結(jié)構(gòu),適合多種不同的應(yīng)用場景。1.使用Redis做緩存Redis的字符串、哈希表兩種數(shù)據(jù)結(jié)構(gòu)適合用來儲存大量的鍵值對信息,從而實現(xiàn)高速緩存。2.使用Redis做隊列Redis有多幾種數(shù)據(jù)結(jié)構(gòu)適于做隊列:●使用“列表”數(shù)據(jù)結(jié)構(gòu),可以實現(xiàn)普通級和優(yōu)先級隊列的功能?!袷褂谩坝行蚣稀睌?shù)據(jù)結(jié)構(gòu),可以實現(xiàn)優(yōu)先級隊列;●使用“哈希表”數(shù)據(jù)結(jié)構(gòu),可以實現(xiàn)延時隊列。3.使用Redis去重Redis有多幾種數(shù)據(jù)結(jié)構(gòu)適于做去重:●利用“集合”數(shù)據(jù)結(jié)構(gòu),可以實現(xiàn)小批量數(shù)據(jù)的去重;●利用“字符串”數(shù)據(jù)結(jié)構(gòu)的位操作,可以實現(xiàn)布隆過濾器,從而實現(xiàn)超大規(guī)模的數(shù)據(jù)去重;●利用Redis自帶的HyperLogLog數(shù)據(jù)結(jié)構(gòu),可以實現(xiàn)超大規(guī)模數(shù)據(jù)的去重和計數(shù)。4.使用Redis實現(xiàn)積分板Redis的“有序集合”功能可以實現(xiàn)積分板功能,還能實現(xiàn)自動排序、排名功能。5.使用Redis實現(xiàn)“發(fā)布/訂閱”功能Redis自帶的“發(fā)布/訂閱”模式可以實現(xiàn)多對多的“發(fā)布/訂閱”功能。\h1.3如何學(xué)習(xí)MongoDB和Redis本節(jié)談一談如何學(xué)習(xí)MongoDB和Redis。\h1.3.1項目驅(qū)動,先用再學(xué)“先看理論,再實做”的學(xué)習(xí)方法,最容易讓人昏昏欲睡。如果先看理論,由于不知道具體的應(yīng)用場景,學(xué)起來就難以抓住重點。如果先給出一個項目,然后根據(jù)完成這個項目需要哪些知識點去針對性地學(xué)習(xí),就能很容易找到重點,活學(xué)活用。在完成項目的同時,也就學(xué)好了知識點。\h1.3.2系統(tǒng)梳理,由點到面項目驅(qū)動也并非完美無缺?;陧椖縼韺W(xué)習(xí),容易導(dǎo)致的問題是知識點零碎而不成系統(tǒng)。因此,在完成一個項目后,應(yīng)對項目涉及的知識點進行系統(tǒng)性的學(xué)習(xí)。例如,聊天網(wǎng)站需要使用Redis的列表,那么在完成了聊天網(wǎng)站后,就應(yīng)該詳細(xì)了解Redis列表的其他命令。又比如,在問答系統(tǒng)中需要使用MongoDB的聯(lián)集合查詢,那么在完成項目以后,應(yīng)根據(jù)聯(lián)集合查詢用到的“aggregate”命令去了解MongoDB的聚合操作。在了解了聚合操作以后,再思考聚合操作的其他應(yīng)用場景。\h1.3.3分清主次,不要在無謂的操作中浪費時間搭建環(huán)境是很多人學(xué)習(xí)的“攔路虎”。由于電腦環(huán)境的差異,可能有一些讀者無論如何都無法在自己的電腦上把數(shù)據(jù)庫運行起來。此時,千萬不要戀戰(zhàn)。趕緊重裝系統(tǒng)、更換電腦、求助他人,或者使用別人已經(jīng)搭建好的環(huán)境。首先學(xué)會使用數(shù)據(jù)庫,等基于MongoDB或者Redis的程序能夠完美運行了,再來慢慢考慮環(huán)境搭建的問題。至于MongoDB的分庫、分表、集群,Redis的集群、哨兵等內(nèi)容,除非你想成為數(shù)據(jù)庫工程師,否則,可以等到熟練使用MongoDB和Redis后,再找大塊空閑時間來了解。\h1.3.4在不同領(lǐng)域中嘗試MongoDB與Redis在多個領(lǐng)域中都有重要的應(yīng)用。例如:●在爬蟲開發(fā)中,MongoDB主要用來寫數(shù)據(jù),Redis主要用來緩存網(wǎng)址?!裨跀?shù)據(jù)分析中,MongoDB的聚合操作用得較多?!裨诤蠖碎_發(fā)中,主要用到MongoDB的增、刪、改、查功能,Redis主要用來做緩存?!裨谟螒蜷_發(fā)中,Redis可以用來做排名功能。如果希望更好地掌握MongoDB和Redis,那么可以在多個領(lǐng)域都尋找項目來進行嘗試,從而更全面地了解各個功能和應(yīng)用場景。\h1.4如何使用本書\h1.4.1本書的產(chǎn)品定位本書旨在教會讀者在不同應(yīng)用場景下正確使用MongoDB和Redis的不同功能,不會介紹數(shù)據(jù)庫的底層原理,也不會介紹如何優(yōu)化數(shù)據(jù),更不會介紹如何搭建數(shù)據(jù)庫集群。如果以開車作為比喻,學(xué)習(xí)開車不需要知道汽車的所有組成元件,也不需要知道汽車為什么踩下油門就可以跑,更不需要知道汽車是如何組裝的。誠然,技藝高超的賽車手確實需要知道汽車的一些底層原理,但前提是要會開車,再來考慮如何開得好。幾乎找不到不用數(shù)據(jù)庫的互聯(lián)網(wǎng)公司。似乎在任何場景下都要用到數(shù)據(jù)庫,但數(shù)據(jù)庫絕不僅僅是保存數(shù)據(jù)那樣簡單,數(shù)據(jù)庫的不同功能有不同的適用場景。如何在適當(dāng)?shù)膱鼍跋逻x擇最適當(dāng)?shù)墓δ?,正是本書需要教給讀者的。本書雖然也有數(shù)據(jù)庫搭建的內(nèi)容,但希望讀者耗費在搭建數(shù)據(jù)庫上的時間不要超過半小時。如果搭建遇到了問題,請立即咨詢朋友、老師,或者使用學(xué)?;蚬疽呀?jīng)搭建好的數(shù)據(jù)庫來進行學(xué)習(xí)。絕對不應(yīng)該在搭建數(shù)據(jù)庫上耗費太多時間。\h1.4.2本書適用的讀者群體本書不適合希望成為數(shù)據(jù)庫工程師的讀者。本書強調(diào)如何將MongoDB和Redis應(yīng)到實際項目中,因此本書會使用編程語言Python來操作數(shù)據(jù)庫,這就要求讀者必須有Python基礎(chǔ)。如果讀者對Python不熟悉,可以參考李金洪老師編著的《Python帶我起飛——入門、進階、商業(yè)實戰(zhàn)》(電子工業(yè)出版社出版)一書。本書適合有Python基礎(chǔ)的后端工程師、爬蟲工程師、數(shù)據(jù)工程師、數(shù)據(jù)科學(xué)家、數(shù)據(jù)挖掘工程師、游戲開發(fā)工程師等群體閱讀學(xué)習(xí)。1.后端工程師本書中涉及的網(wǎng)站是使用Flask開發(fā)的,后端工程師在學(xué)習(xí)了MongoDB與Redis知識后,可以參考本書的網(wǎng)站源代碼舉一反三,使用MongoDB與Redis來優(yōu)化自己網(wǎng)站的后臺代碼,從而提高速度或者簡化邏輯。2.爬蟲工程師MongoDB特別適合寫入大批量、高并發(fā)、不規(guī)則的數(shù)據(jù),Redis特別適合作為分布式爬蟲的連接樞紐。爬蟲工程師在學(xué)習(xí)了MongoDB與Redis后,可以大大提高爬蟲的開發(fā)效率和運行效率。3.?dāng)?shù)據(jù)工程師、數(shù)據(jù)科學(xué)家、數(shù)據(jù)挖掘工程師這個群體的讀者,可以使用MongoDB來保存數(shù)據(jù),并使用MongoDB的聚合查詢功能來對數(shù)據(jù)進行一些基本的查詢操作和清洗操作,從而輸出格式較為規(guī)范的數(shù)據(jù),以便進行進一步分析。4.游戲工程師Redis特別適合用來存放一些中間數(shù)據(jù)。另外,Redis自帶的一些數(shù)據(jù)結(jié)構(gòu)天然適合用來實現(xiàn)游戲中的一些功能,例如積分板、去重、高速緩存等。\h1.4.3如何利用本書實例進行練習(xí)本書有大量的實例供讀者練習(xí)。實例分為小型、中型和大型三種。1.小型實例對于小型實例,讀者可以根據(jù)書中的描述直接在MongoDB圖形化管理軟件、Redis交換環(huán)境或Python交互環(huán)境中進行操作。這種實例包括(但不限于)MongoDB與Redis的基本語法、基本操作。2.中型實例對于中型實例,由于需要完成較多的Python代碼,因此需要在Python的集成開發(fā)環(huán)境(PyCharm等)中完成。本書會為中型實例提供原始數(shù)據(jù)的生成程序。只要運行生成程序,就會在MongoDB或者Redis中寫入練習(xí)專用的原始數(shù)據(jù)。然后,讀者就可以操作這些原始數(shù)據(jù)進行學(xué)習(xí)。3.大型實例對于大型的實例,本書會附送相應(yīng)的代碼(一個網(wǎng)站的所有源文件)。讀者根據(jù)書中的使用說明,可以在自己電腦上將網(wǎng)站的運行環(huán)境搭建起來。在項目環(huán)境能正常運行后,讀者只需要完成項目中的MongoDB或Redis模塊,就可以使整個網(wǎng)站按照預(yù)期的效果正常工作。\h第2章數(shù)據(jù)存儲方式的演進對于小批量的數(shù)據(jù),可以使用“記事本”程序?qū)⑵浔4娴接脖P里。但如果數(shù)據(jù)量越來越多,類型越來復(fù)雜,使用“記事本”程序保存就難以查詢和修改。數(shù)據(jù)庫的出現(xiàn),就是為了便于從大量數(shù)據(jù)中查詢和修改內(nèi)容。在程序開發(fā)中,常常涉及一些中間數(shù)據(jù),這些中間數(shù)據(jù)會被頻繁讀/寫。如果僅僅把中間數(shù)據(jù)放在內(nèi)存中,則不便于從外界觀察程序運行到了什么狀態(tài)。而把中間數(shù)據(jù)保存到基于硬盤的傳統(tǒng)數(shù)據(jù)庫,又會影響程序性能。內(nèi)存數(shù)據(jù)庫的出現(xiàn),就解決了這個問題。\h2.1從文件到MongoDB數(shù)據(jù)庫\h2.1.1使用文件保存數(shù)據(jù)對于少量數(shù)據(jù),可以使用“記事本”程序來保存。但如果需要對數(shù)據(jù)進行計算,那么記事本顯然就不能勝任了。此時可以考慮Excel。還可以使用Excel的數(shù)據(jù)透視表來統(tǒng)計數(shù)據(jù),如圖2-1所示。圖2-1使用數(shù)據(jù)透視表統(tǒng)計數(shù)據(jù)Excel的一張表可以存放100萬行左右的數(shù)據(jù),那如果每天的數(shù)據(jù)都超過100萬行呢?此時就不得不使用數(shù)據(jù)庫來保存了。\h2.1.2使用MongoDB保存數(shù)據(jù)使用數(shù)據(jù)庫,可以保存大量的數(shù)據(jù),這是數(shù)據(jù)庫最基本的功能。另外,數(shù)據(jù)庫還能夠?qū)?shù)據(jù)進行邏輯運算、數(shù)學(xué)運算、搜索、批量修改或刪除。相比于傳統(tǒng)的關(guān)系型數(shù)據(jù)庫,MongoDB對于每一次插入的字段格式?jīng)]有要求,字段可以隨意變動,字段類型也可以隨意變動,如圖2-2所示。圖2-2MongoDB對字段格式與內(nèi)容不做限制MongoDB可以并發(fā)插入上萬條文檔,這是傳統(tǒng)關(guān)系型數(shù)據(jù)庫所不能望其項背的。\h2.2從隊列Queue到Redis在某些場景下,使用隊列可以提高程序的運行性能,但如何選擇合適的隊列也需要仔細(xì)考慮。\h2.2.1了解“生產(chǎn)者/消費者”模型在餐館吃飯時,廚師做完一道菜后就會把菜從傳菜窗口遞出去,然后繼續(xù)做下一道菜。廚師不需要關(guān)心顧客是不是已經(jīng)把菜吃完了。如果廚師做菜的速度大于顧客拿菜的速度,那么就會有越來越多的菜堆在傳菜窗口。如果顧客拿菜的速度大于廚師做菜的速度,那么傳菜窗口始終是空的,來一道菜就會立刻被拿走。在程序開發(fā)中,這就是一個典型的“生產(chǎn)者/消費者”模型:廚師是生產(chǎn)者,負(fù)責(zé)生產(chǎn);顧客是消費者,負(fù)責(zé)消費。廚師和顧客各做各的事情。傳菜窗口就是隊列,它把生產(chǎn)者與消費者聯(lián)系在一起。\h2.2.2實例1:使用Python實現(xiàn)隊列實例描述使用Python自帶的queue對象來實現(xiàn)隊列:(1)使用Python實現(xiàn)一個簡單的“生產(chǎn)者/消費者”模型。(2)使用Python的queue對象做信息隊列。在Python使用多線程實現(xiàn)生產(chǎn)者與消費者的程序中,可以使用Python自帶的queue對象來作為生產(chǎn)者與消費者溝通的隊列。在代碼2-1中,生產(chǎn)者負(fù)責(zé)產(chǎn)生兩個數(shù)字,消費者負(fù)責(zé)把兩個數(shù)字相加。代碼2-1簡單的“生產(chǎn)者/消費者”隊列生產(chǎn)者固定每兩秒生產(chǎn)一組數(shù),然后把這一組數(shù)放進隊列里。消費者每次從隊列里面取一組數(shù),將它們相加然后打印出來。消費者取一次數(shù)的時間是1~10秒中的一個隨機時間。由于生產(chǎn)過程和消費過程的時間不對等,所以,可能會出現(xiàn)生產(chǎn)者生產(chǎn)的數(shù)據(jù)堆積在隊列中的情況,如圖2-3所示。圖2-3生產(chǎn)的數(shù)據(jù)堆積\h2.2.3Python的Queue及其缺陷代碼2-1的運行結(jié)果存在兩種情況:●如果消費者每次暫停的時間都小于2秒,那么隊列始終是空的,來一組數(shù)立刻就被消費?!袢绻M者每次暫停的時間都大于2秒,那么隊列里的數(shù)就會越來越多。但是,由于消費者暫停時間是隨機的,我們不能提前知道它每次會暫停多久。假定程序運行了1小時,請問隊列里有多少數(shù)據(jù)?如果使用Python自帶的隊列,就會出現(xiàn)以上的疑問。因為開發(fā)者不能直接看到隊列的長度。如果開發(fā)者一開始就考慮到“需要隨時觀察隊列長度”這個需求,那么可以通過對代碼做一些修改來實現(xiàn)。但如果一開始沒有打算觀察隊列長度,僅僅是臨時起意,那該怎么辦?如果不僅想看隊列長度,還想看里面每一組數(shù)都是什么,又該如何操作?假設(shè)隊列里已經(jīng)堆積了一百組數(shù),現(xiàn)在想增加消費者,該怎么增加?如再運行一個Python程序,那能去讀第一個正在運行中的Python程序中的隊列嗎?Python把隊列中的數(shù)據(jù)存放在內(nèi)存中。如果電腦突然斷電,那隊列里的數(shù)是不是全都丟失了?為了防止丟數(shù)據(jù),是否需要把數(shù)據(jù)持久化到硬盤?那持久化的代碼怎么寫,代碼量有多少,考不考慮并發(fā)和讀寫沖突?為了解決上述問題,在代碼2-1的基礎(chǔ)上,代碼量要翻倍翻倍再翻倍。\h2.2.4實例2:使用Redis替代Queue實例描述使用Redis作為隊列,從而解決實例1中遇到的各種問題。(1)拆分“生產(chǎn)者/消費者”隊列。(2)使用Redis的列表作為隊列。如果使用Redis代替Python自帶的隊列,解決2.2.3小節(jié)中提出的所有問題,則代碼量的變化甚至可以忽略不計。把生產(chǎn)者代碼和消費者代碼分別寫到兩個文件中。1.生產(chǎn)者代碼代碼2-2使用Redis后的生產(chǎn)者代碼2.消費者代碼代碼2-3使用Redis后的消費者代碼提示:讀者不必太糾結(jié)本章中的代碼,本書后面的章會對各個知識點做詳細(xì)的解讀。現(xiàn)在,生產(chǎn)者和消費者可以放在不同的機器上運行,想運行多少個消費者就運行多少個消費者,想什么時候增加消費者都沒有問題。如果想觀察當(dāng)前隊列里有多少數(shù)據(jù),或者想看看具體有哪些數(shù)據(jù)在隊列里,則執(zhí)行一條命令:“l(fā)len隊列名稱”即可。圖2-4中,當(dāng)前隊列中已經(jīng)堆積了35組數(shù)據(jù)。圖2-4觀察當(dāng)前隊列中有多少數(shù)據(jù)Redis自己會對數(shù)據(jù)做持久化處理,所以,即使電腦斷電也不必?fù)?dān)心。甚至,開發(fā)者還可以通過修改隊列中的數(shù)據(jù),從而影響消費者的輸出結(jié)果。\h本章小結(jié)本章簡單介紹了MongoDB與Redis的兩個應(yīng)用實例,從而引出了MongoDB和Redis在實際應(yīng)用中的優(yōu)勢。其中,MongoDB可以用來保存大量數(shù)據(jù),且字段和格式均可以隨意改變;Redis擴展了隊列的應(yīng)用范圍,使得開發(fā)者可以方便地觀察程序的運行狀況,甚至在運行中改變程序的行為。\h第2篇快速入門非關(guān)系型數(shù)據(jù)庫有著強大的擴展能力,不需要事先定義好數(shù)據(jù)庫中的字段,數(shù)據(jù)插入速度遠(yuǎn)超關(guān)系型數(shù)據(jù)庫。第3章會介紹MongoDB的安裝和基本語法。另外,介紹在圖形化管理工具Robo3T中操作MongoDB,以及使用Python操作MongoDB的方法。第4章會以實例的形式鞏固MongoDB的基礎(chǔ)知識。第5章會介紹Redis的安裝和基本語法,以及使用Python操作Redis的方法。第6章會以實例的形式鞏固Redis的基礎(chǔ)知識。\h第3章MongoDB快速入門MongoDB的語法與Python非常相似。在很多情況下,操作MongoDB的代碼都可以直接用到Python中。所以,結(jié)合Python來學(xué)習(xí)MongoDB可以起到事半功倍的效果。\h3.1MongoDB和SQL術(shù)語對比SQL與MongoDB術(shù)語對比見表3-1。表3-1SQL與MongoDB術(shù)語對比\h3.2安裝MongoDB\h3.2.1在Windows中安裝(1)訪問MongoDB官網(wǎng)的下載頁面(/download-center?jmp=nav#community),單擊“DOWNLOAD(msi)”按鈕,如圖3-1所示。圖3-1從MongoDB官網(wǎng)下載Windows版MongoDB(2)雙擊下載的文件(如無特殊說明,只需要一直單擊“Next”按鈕即可)。在安裝過程中將會看到如圖3-2所示的界面選擇安裝方式,這里單擊“Custom”按鈕。(3)修改文件的安裝路徑到C:\ProgramFiles\MongoDB,單擊“Next”按鈕進行安裝,如圖3-3所示。圖3-2單擊“Custom”按鈕圖3-3修改文件安裝路徑(4)安裝完成以后,進入C:\ProgramFiles\MongoDB\bin,可以看到如圖3-4所示的內(nèi)容。圖3-4安裝完成后的文件內(nèi)容(5)將這里的所有文件全部復(fù)制并粘貼到C:\MongoDB\下,以方便管理。手動創(chuàng)建存放數(shù)據(jù)文件的文件夾“C:\MongoDB\Data”,以及存放日志文件的文件夾“C:\MongoDB\Log”。最后使用記事本創(chuàng)建配置文件,配置文件的內(nèi)容見代碼3-1。代碼3-1MongoDB配置文件(6)將配置文件保存在“C:\MongoDB\mongod.conf”。此時,C:\MongoDB\下的內(nèi)容如圖3-5所示。在D:\MongoDB的安裝文件夾中的空白位置,按住Shift鍵并單擊鼠標(biāo)右鍵,在彈出的菜單中選擇“在此處打開命令窗口”命令,然后輸入以下代碼啟動MongoDB:mongod.exe--configmongod.conf圖3-5創(chuàng)建文件夾和配置文件以后的MongoDB文件夾運行MongoDB以后,由于日志文件(Log)都已經(jīng)被寫到文件C:\MongoDB\Log\mongo.log中了。因此控制臺中就什么都沒有顯示,如圖3-6所示。這是正?,F(xiàn)象。圖3-6MongoDB在Windows中運行不會有內(nèi)容打印出來\h3.2.2在Linux中安裝由于Linux有眾多的發(fā)行版,不同發(fā)行版本有不同的包管理工具,所以在各個發(fā)行版本中安裝MongoDB的命令可能會有一些差異。本書以Ubuntu18.04與Ubuntu16.04為例,來說明如何安裝MongoDB。1.在Ubuntu18.04中安裝MongoDB(1)安裝。在Ubuntu18.04中安裝MongoDB非常簡單,只需要執(zhí)行以下兩行命令:sudoaptupdatesudoaptinstall-ymongodb(2)確認(rèn)MongoDB是否正常。Ubuntu18.04版的MongoDB自帶了一個配置文件(/etc/mongod.conf)。MongoDB被安裝后,系統(tǒng)會以這個配置文件為基準(zhǔn),自動以服務(wù)的方式啟動它。所以,MongoDB安裝完成后就自啟動了,不需要運行額外的命令來啟動。但是,可以通過以下命令來確認(rèn)MongoDB是否正常運行:systemctlstatusmongodb圖3-7中方框框住的“active(running)”表示MongoDB正在運行。圖3-7觀察MongoDB是否正常運行提示:如果不是以root賬戶登錄Ubuntu,則執(zhí)行systemctl命令時需要加上“sudo”,如下:sudosystemctlstatusmongodb2.在Ubuntu16.04中安裝MongoDB首先添加MongoDB的源,見代碼3-2。代碼3-2在Ubuntu16.04中安裝MongoDB其中主要代碼說明如下?!竦?行代碼:導(dǎo)入包管理程序的公鑰?!竦?行代碼:創(chuàng)建MongoDB需要用到的列表文件?!竦?行代碼:安裝MongoDB。提示:Ubuntu16.04版的MongoDB也自帶配置文件,地址為:/etc/mongod.conf。3.啟動MongoDB安裝完成后,MongoDB服務(wù)并不會自動啟動,需要使用systemctl命令來啟動,具體命令如下:sudosystemctlstartmongod#啟動MongoDBsudosystemctlenablemongod#把MongoDB設(shè)置為開機啟動提示:在Ubuntu18.04中執(zhí)行systemctl命令時,MongoDB對應(yīng)的名字為“mongodb”。在Ubuntu16.04中,MongoDB對應(yīng)的名字為“mongod”,請注意區(qū)分。\h3.2.3在macOS中安裝1.使用Homebrew安裝并啟動MongoDBHomebrew是macOS系統(tǒng)中非常優(yōu)秀的第三方包管理工具。如果讀者已經(jīng)安裝過Homebrew,則再安裝MongoDB就變得極其簡單。執(zhí)行以下命令即可完成安裝。brewupdatebrewinstallmongodb使用Homebrew安裝的MongoDB會自動生成配置文件。在安裝完成以后,直接使用以下命令啟動MongoDB:mongod--config/usr/local/etc/mongod.conf2.使用普通方式安裝在終端中輸入以下命令來下載、解壓MongoDB到~/chapter_3/mongo/mongodb文件夾中,見代碼3-3。代碼3-3手動安裝MongoDB其中,主要代碼說明如下?!竦?、2行代碼:創(chuàng)建文件夾?!竦?行代碼:進入剛剛創(chuàng)建的文件夾?!竦?行代碼:下載MongoDB的壓縮包。tgz是一種壓縮格式。●第5行代碼:把壓縮包解壓到當(dāng)前文件夾?!竦?行代碼:把解壓后的MongoDB文件復(fù)制到剛剛新創(chuàng)建的mongodb文件夾中。運行效果如圖3-8所示。圖3-8手動安裝MongoDB安裝完成后,在~/chapter_3/mongo/mongodb/bin文件夾下可以看到如圖3-9所示的各個文件。圖3-9MongoDB文件夾與Windows一樣,在macOS下使用這種方式,MongoDB不會自動創(chuàng)建配置文件,因此需要進一步配置。(1)在~/chapter_3/mongo/mongodb/bin文件夾下,手動創(chuàng)建兩個文件夾——log和data。提示:可以直接在終端里使用“mkdir”命令創(chuàng)建。也可以用訪達(Finder)打開~/chapter_3/mongo/mongodb/bin文件夾,如圖3-10所示,然后在圖形界面下創(chuàng)建log和data文件夾。圖3-10在圖形界面中進入~/chapter_3/mongo/mongodb/bin文件夾(2)使用任何一個適合寫代碼的文本編輯器(如Vim/VisualStudioCode/Sublime/Atom等),編寫內(nèi)容見代碼3-4中的內(nèi)容,然后將編寫的代碼保存到~/chapter_3/mongo/mongodb/bin/mongodb.conf中。代碼3-4MongoDB的配置文件(3)配置后的文件結(jié)構(gòu)如圖3-11所示。圖3-11添加配置文件后的文件結(jié)構(gòu)接下來,啟動MongoDB的方法和通過Homebrew安裝MongoDB后的啟動方式差不多了。在終端中,先進入存放MongoDB的文件夾,再啟動MongoDB:cd~/chapter_3/mongo/mongodb/binmongod--configmongodb.conf如同另外兩個系統(tǒng)一樣,運行以后不會有內(nèi)容打印出來,但是MongoDB已經(jīng)正常啟動了,如圖3-12所示。圖3-12運行MongoDB\h3.3MongoDB的圖形化管理軟件——Robo3TMongoDB雖然自帶了一個終端環(huán)境下的客戶端,但是操作起來比較繁瑣,數(shù)據(jù)顯示也不夠直觀。因此需要使用一個圖形界面管理軟件來提高MongoDB數(shù)據(jù)的可讀性。\h3.3.1安裝Robo3T是一個跨平臺的MongoDB管理工具,采用圖形界面查詢或者修改MongoDB。Robo3T的下載地址為:/download。提示:在下載頁面中可以看到另一個叫作Studio3T的軟件,它是一個功能更加強大的MongoDB圖形化管理軟件。但它是一個商業(yè)軟件,需要收費。而Robo3T是開源軟件并且免費,它的功能足夠應(yīng)付本書的所有應(yīng)用場景,因此本書選擇使用Robo3T。1.安裝Robo3TRobo3T的安裝沒有任何需要特別說明的地方,和安裝普通軟件一樣簡單?!袢绻到y(tǒng)是Windows與Linux,則安裝完成后就可以使用了。●如果系統(tǒng)是macOS,則安裝完成后第一次運行時可能會看到如圖3-13所示的安全提示。圖3-13MacOS的安全提示解決這個問題的方法如下:(1)打開macOS的“系統(tǒng)設(shè)置”,單擊“Security&Privacy”(中文名為“安全和隱私”)圖標(biāo),如圖3-14所示。圖3-14單擊“安全和隱私”圖標(biāo)(2)在“安全和隱私”設(shè)置界面,單擊“OpenAnyway”(中文名為“仍然運行”)按鈕,如圖3-15所示。圖3-15單擊“仍然運行”按鈕(3)在彈出的對話框中單擊“Open”(中文名為“運行”)按鈕即可打開Robo3T,如圖3-16所示。圖3-16單擊“運行”按鈕打開Robo3T(4)第一次成功啟動Robot3T時,會看到一個用戶協(xié)議,如圖3-17所示。勾選“Iagree”并單擊“Next”按鈕。(5)在下一個界面中添加名字公司之類的信息,可以直接忽略,單擊“Finish”按鈕跳過即可。圖3-17用戶協(xié)議2.用Robo3T連接MongoDB(1)打開Robo3T,看到如圖3-18所示對話框,單擊左上角“Create”鏈接。圖3-18初次運行RoboMongo的界面(2)彈出如圖3-19所示對話框。如果MongoDB就在本地電腦中運行,則只需在“Name”欄中填寫一個名字,其他地方不需要修改,然后直接單擊“Save”按鈕。圖3-19在“Name”這一欄填寫名字即可(3)回到如圖3-18所示界面,單擊“Connect”按鈕就可以連接MongoDB了。\h3.3.2認(rèn)識Robo3T的界面Robo3T的主界面如圖3-20所示。重點關(guān)注A、B、C三個區(qū)域。圖3-20Robo3T主界面●數(shù)據(jù)庫列表區(qū)(后簡稱A區(qū)域),用于選擇數(shù)據(jù)庫和集合。●數(shù)據(jù)展示區(qū)(后簡稱B區(qū)域),用于顯示數(shù)據(jù)?!衩顖?zhí)行區(qū)(后簡稱C區(qū)域),用于編寫MongoDB代碼。在A區(qū)域中,單擊數(shù)據(jù)庫圖標(biāo)左邊的箭頭,展開數(shù)據(jù)庫;單擊“Collections”左邊的箭頭,展開集合。雙擊集合的名字,則B區(qū)域和C區(qū)域發(fā)生相應(yīng)的變化。本書主要和A、B、C這三個區(qū)域打交道。每一個區(qū)域的具體功能會在使用時詳細(xì)介紹。\h3.4MongoDB的基本操作增、查、改、刪是所有數(shù)據(jù)庫必備的功能。本節(jié)將介紹如何使用MongoDB來實現(xiàn)這四個功能。\h3.4.1實例3:創(chuàng)建數(shù)據(jù)庫與集合,寫入數(shù)據(jù)實例描述在Robo3T中進行如下操作。(1)創(chuàng)建一個名為“chapter_3”的數(shù)據(jù)庫,以及其中的多個集合。(2)往集合里逐條插入數(shù)據(jù)。(3)往集合里批量插入數(shù)據(jù)。使用Robo3T打開剛剛安裝完成的MongoDB,可以看到A區(qū)域是空的,還沒有數(shù)據(jù)庫,如圖3-21所示。圖3-21MongoDB是空的1.創(chuàng)建數(shù)據(jù)庫與集合(1)鼠標(biāo)右擊“小電腦”圖標(biāo),在彈出的菜單中選擇“CreateDatabase”命令,如圖3-22所示。(2)在彈出的對話框中輸入數(shù)據(jù)庫的名字,單擊“Create”按鈕完成數(shù)據(jù)庫的創(chuàng)建,如圖3-23所示。圖3-22選擇“CreateDatabase”命令圖3-23輸入數(shù)據(jù)庫名字并單擊Create按鈕(3)新創(chuàng)建的數(shù)據(jù)庫會出現(xiàn)在A區(qū)域中。單擊數(shù)據(jù)庫左邊的小箭頭將其展開,然后右擊“Collections(0)”文件夾,在彈出的菜單中選擇“CreateCollection...”命令,如圖3-24所示。(4)在彈出的對話框中輸入集合的名字,然后單擊“Create”按鈕(如圖3-25所示)創(chuàng)建一個集合。圖3-24選擇“CreateCollection...”命令圖3-25輸入集合名字并單擊“Create”按鈕(5)創(chuàng)建完集合后,原來的“Collections(0)”變成了“Collections(1)”。由此可以推測:括號里面的數(shù)字表示這個數(shù)據(jù)庫里面有多少個集合。單擊“Collections(1)”左側(cè)的小箭頭將其展開,可以看到集合“example_data_1”已經(jīng)創(chuàng)建好了。雙擊集合名字,可以看到當(dāng)前集合里什么都沒有,如圖3-26所示。圖3-26空集合什么都沒有2.插入單條數(shù)據(jù)插入單條數(shù)據(jù)的命令為“insertOne()”。Robo3T自帶插入數(shù)據(jù)的功能。但是本書不準(zhǔn)備介紹。本書會直接介紹如何在C區(qū)域執(zhí)行MongoDB命令插入數(shù)據(jù)。(1)創(chuàng)建一條JSON字符串。例如:{"name":"張小二","age":17,"address":"浙江"}(2)對C區(qū)域的內(nèi)容做一些修改。原來是:db.getCollection('example_data_1').find({})修改為:db.getCollection('example_data_1').insertOne({"name":"張小二","age":17,"address":"浙江"})(3)使用Windows與Linux的讀者,可以按鍵盤上的“Ctrl+R”組合鍵;使用macOS的讀者按“Command+R”組合鍵。運行后的界面如圖3-27所示??梢钥吹剑粭l數(shù)據(jù)已經(jīng)插入到了MongoDB中。圖3-27插入數(shù)據(jù)提示:還可以通過單擊Robo3T上面的綠色三角形來運行命令。(4)在A區(qū)域雙擊集合“example_data_1”,從新打開的選項卡中可以看到數(shù)據(jù)已經(jīng)成功插入,如圖3-28所示。圖3-28數(shù)據(jù)已經(jīng)成功插入被插入的數(shù)據(jù)就是JSON字符串:{"name":"張小二","age":17,"address":"浙江"}提示:JSON字符串必須使用雙引號,不過這個規(guī)定在MongoDB中并非強制性的,用單引號也沒有問題。例如,在C區(qū)域執(zhí)行以下命令:db.getCollection('example_data_1').insertOne({'name':’王小六’,'age':25,'work':’廚師’})插入以后,集合“example_data_1”中的數(shù)據(jù)如圖3-29所示。圖3-29插入第二條數(shù)據(jù)如果將Python的字典直接復(fù)制到MongoDB的insertOne命令中,則絕大部分情況下這些字典都可以直接使用,只有極少數(shù)情況下需要做一些修改。3.4節(jié)將會講到這些少數(shù)情況。提示:MongoDB還允許Key不帶引號,直接寫成{name:’王小六’,age:25,work:’廚師’}。但這種寫法存在一些局限性,并且會導(dǎo)致MongoDB的命令不方便平滑移植到Python中。因此,建議讀者一律使用帶單引號的寫法或者帶雙引號的寫法。3.調(diào)整插入的字段(1)任意修改、添加、刪除字段。在圖3-29中,第1條數(shù)據(jù)沒有“work”這個字段,第2條數(shù)據(jù)沒有“address”這個字段。這就說明:在MongoDB里,插入數(shù)據(jù)的字段是可以任意修改、添加、刪除的。例如,再插入一條新的數(shù)據(jù):這一次所有的字段都和前兩條數(shù)據(jù)不一樣,但MongoDB仍然可以輕松處理——遇到新來的字段,加上去就是了,沒什么大不了的,如圖3-30所示。圖3-30遇到新的字段,MongoDB會自動添加上去(2)插入同一個字段,但格式卻不同。即使是同一個字段,其數(shù)據(jù)格式也可以不一樣。例如,再插入一條數(shù)據(jù):添加后的數(shù)據(jù)如圖3-31所示。圖3-31同一個字段的數(shù)據(jù)格式也可以不一樣提示:“能不能做”是一回事,“應(yīng)不應(yīng)該做”是另一回事。雖然MongoDB能夠處理同一個字段的不同數(shù)據(jù)類型,也可以隨意增減字段,但并不意味著應(yīng)該這樣做。在設(shè)計數(shù)據(jù)庫時,應(yīng)盡量保證同一個字段使用同一種類型的數(shù)據(jù),并提前考慮好應(yīng)該有哪些字段。3.批量插入數(shù)據(jù)批量插入數(shù)據(jù)的命令是“insertMany”?,F(xiàn)在把一個包含很多個字典的列表傳給“insertMany”。列表為:對應(yīng)的MongoDB批量插入語句為:運行后返回的數(shù)據(jù)如圖3-32所示。圖3-32批量插入數(shù)據(jù)提示:可以通過換行和縮進讓代碼更美觀、易讀。換行和縮進不影響代碼功能。運行以后的集合數(shù)據(jù)如圖3-33所示。圖3-33插入數(shù)據(jù)以后的集合無論是插入一條數(shù)據(jù)還是插入多條數(shù)據(jù),每一條數(shù)據(jù)被插入MongoDB后都會被自動添加一個字段“_id”。“_id”讀作“ObjectId”,它是由時間、機器碼、進程pid和自增計數(shù)器構(gòu)成的?!癬id”始終遞增,但絕不重復(fù)?!裢粫r間,不同機器上面的“_id”不同?!裢粰C器,不同時間的“_id”也不同。●同一機器同一時間批量插入的數(shù)據(jù),“_id”依然不同。提示:_id的前8位字符轉(zhuǎn)換為十進制就是時間戳。例如“5b2f2e24e0f42944105c81d2”,前8位字符“5b2f2e24”轉(zhuǎn)換為十進制就是時間戳“1529818660”,對應(yīng)的北京時間是“2018-06-2413:37:40”。\h3.4.2實例4:查詢數(shù)據(jù)實例描述對數(shù)據(jù)集example_data_1進行如下查詢:(1)查詢所有數(shù)據(jù)。(2)查詢特定數(shù)據(jù):查詢“age”為25歲的員工。(3)查詢特定數(shù)據(jù):查詢“age”不小于25的所有記錄。(4)限定返回的數(shù)據(jù)字段類型。在Robo3T中雙擊集合名字,實際上是自動執(zhí)行了以下這條查詢語句:db.getCollection('example_data_1').find({})下面先來了解一下查詢結(jié)果的三種顯示模式。1.三種顯示模式Robo3T顯示出來的查詢結(jié)果如圖3-34所示。注意右上角方框框住的三個圖標(biāo)。圖3-34查詢并返回所有數(shù)據(jù)Robo3T對于返回的數(shù)據(jù)有三種組織方式,從左到右分別是:“樹形模式(TreeMode)”“表格模式(TableMode)和“文本模式(TextMode)”。提示:這三種顯示模式是Robo3T提供的,不是MongoDB的功能。(1)樹形模式。優(yōu)點是:可以直觀地看到每一條記錄有哪些字段,每一個字段是什么內(nèi)容和什么格式,如圖3-35所示。弊端是:每次都要單擊每一條記錄左邊的三角形,非常麻煩。圖3-35樹形模式(2)表格模式(本書用得最多的顯示模式)。優(yōu)點是:便于對數(shù)據(jù)整體有一個全面的認(rèn)識。在表格模式里可以看到很多行數(shù)據(jù),便于觀察數(shù)據(jù)的全貌、對比不同記錄的相同字段,如圖3-36所示。弊端是:不能顯示嵌入式文檔的內(nèi)容。圖3-36表格模式(3)文本模式(如圖3-37所示)。優(yōu)點是:便于對數(shù)據(jù)進行復(fù)制/粘貼,便于對特殊格式數(shù)據(jù)進行深入認(rèn)識。弊端是:一屏只能顯示少量內(nèi)容,要反復(fù)拖動滾動條才能完整看完數(shù)據(jù);不方便不同記錄之間進行對比。圖3-37文本模式2.查詢固定值數(shù)據(jù)(1)查詢所有數(shù)據(jù)。如要查詢所有數(shù)據(jù)值,則直接使用下面兩種寫法的任意一種即可:db.getCollection('example_data_1').find()或db.getCollection('example_data_1').find({})(2)查詢特定數(shù)據(jù)。如要查詢某個或者某些具體字段,則可以使用下面的語法來查詢。如果有多個字段,則這些字段需要同時滿足。例如,對于數(shù)據(jù)集example_data_1,要查詢所有“age”字段為25的記錄。則查詢語句可以寫為:db.getCollection('example_data_1').find({'age':25})查詢結(jié)果如圖3-38所示。圖3-38查詢所有“age”為25的記錄由于“age”為25的記錄有兩條,于是需要進一步縮小查詢范圍——再增加一個限制條件:運行結(jié)果如圖3-39所示??偨Y(jié)一下,“find”的參數(shù)相當(dāng)于一個字典。字典的Key就是字段名,字典的值就是要查詢的值。如果字典有多個Key,則這些字段需同時滿足。圖3-39多個查詢條件同時滿足3.查詢范圍值數(shù)據(jù)如要查詢的字段值能夠比較大小,則查詢時可以限定值的范圍。例如,對數(shù)據(jù)集example_data_1,要查詢所有“age”字段不小于25的記錄,則需要使用大于等于操作符“$gte”。查詢語句如下:db.getCollection('example_data_1').find({'age':{'$gte':25}})運行效果如圖3-40所示。圖3-40查詢范圍數(shù)據(jù)查詢某個范圍的數(shù)據(jù)會用到的操作符見表3-2。表3-2范圍操作符及其意義使用范圍操作符的查詢語句格式如下:可以看出,在使用范圍操作符后,原本填寫被查詢值的地方現(xiàn)在又變成了一個字典。這個字典的Key是各個范圍操作符,而它們的值是各個范圍的邊界值?!九e例1】查詢所有“age”大于21并小于等于24的數(shù)據(jù)。查詢語句如下:db.getCollection('example_data_1').find({'age':{'$lt':25,'$gt':21}})運行效果如圖3-41所示。圖3-41“age”大于21并且小于等于24的所有記錄【舉例2】查詢所有“age”大于21并小于等于24的數(shù)據(jù),且“name”不為“夏侯小七”的記錄,見代碼3-5。代碼3-5查詢“age”大于21并小于等于24,且“name”不為“夏侯小七”的數(shù)據(jù)運行效果如圖3-42所示。圖3-42查詢的結(jié)果4.限定返回哪些字段“find”命令可以接收兩個參數(shù):第1個參數(shù)用于過濾不同的記錄,第2個參數(shù)用于修改返回的字段。如果省略第2個參數(shù),則MongoDB會返回所有的字段。如要限定字段,則查詢語句的格式如下:其中,用于限定字段的字典的Key為各個字段名。其值只有兩個——0或1?!袢绻禐?,則表示在全部字段中剔除值為0的這些字段并返回?!袢绻禐?,則表示只返回值為1的這些字段。例如,查詢數(shù)據(jù)集example_data_1,但不返回“address”和“age”字段。查詢語句如下:db.getCollection('example_data_1').find({},{'address':0,'age':0})運行結(jié)果為如圖3-43所示。圖3-43不返回“address”字段和“age”字段再例如,要求只返回name字段和age字段,則查詢語句如下:db.getCollection('example_data_1').find({},{'name':1,'age':1})運行效果如圖3-44所示。圖3-44只返回“name”和“age”字段讀者可能已經(jīng)發(fā)現(xiàn),不論是選擇“只返回某些字段”還是“不返回某些字段”,結(jié)果里始終有“_id”。這是因為,“_id”比較特殊,它是默認(rèn)要返回的,除非明確說明不需要它。即,如果不想要“_id”,則必須在限定字段的字典中把“_id”字段的值設(shè)為0,如圖3-45所示。圖3-45明確申明不需要“_id”如果不考慮“_id”,則限定字段的字典里面的值只可能全都是0或全都是1,不可能1和0混用,一旦混用則MongoDB就會報錯。這從邏輯上很好理解:(1)如果只要A、B、C,則沒有提到的自然都是不需要的。(2)如果除A、B、C外其他的全都要,則沒有提到的自然全都是需要的。提示:只有“_id”很特別,不論其他字段的值是0還是1,如果不需要返回“_id”,則需要把它的值設(shè)為0。5.修飾返回結(jié)果(1)滿足要求的數(shù)據(jù)有多少條——count()命令。如果想知道滿足要求的數(shù)據(jù)有多少條,則可以使用“count()”命令。例如,要查詢所有“age”字段大于21的記錄有多少條,則查詢語句如下:db.getCollection('example_data_1').find({'age':{'$gt':21}}).count()運行結(jié)果如圖3-46所示。返回數(shù)字“6”表示有6條記錄滿足要求。圖3-46查詢結(jié)果條數(shù)(2)限定返回結(jié)果——“l(fā)imit()”命令。如果查詢的結(jié)果非常多,則可能需要限定返回結(jié)果。此時就需要使用“l(fā)imit()”命令。它的用法如下:●如果限制返回的條數(shù)為一個數(shù)字,則表示最多返回這么多條記錄。如果超過限定條數(shù),則只返回限定的條數(shù)?!袢绻蛔阆薅ǖ臈l數(shù),則有多少就返回多少。例如,對于數(shù)據(jù)集example_data_1,限制只返回4條數(shù)據(jù)。具體命令如下:db.getCollection('example_data_1').find().limit(4)運行效果如圖3-47所示。圖3-47最多返回4條記錄(3)對查詢結(jié)果進行排序——“sort()”命令。有時也需要對查詢結(jié)果進行排序,此時需要使用“sort()”命令。使用方法如下:其中,字段的值為-1表示倒序,為1表示正序。例如,對所有“age”大于21的數(shù)據(jù),按“age”進行倒序排列。查詢語句如下:db.getCollection('example_data_1').find({'age':{'$gt':21}}).sort({'age':-1})運行結(jié)果如圖3-48所示。圖3-48將查詢結(jié)果倒序排列\(zhòng)h3.4.3實例5:修改數(shù)據(jù)實例描述數(shù)據(jù)集example_data_1,“name”為“王小六”的這個記錄是沒有“address”字段的?,F(xiàn)在需要為它增加這個字段,同時把“work”從“廚師”改為“工程師”。(1)更新集合中的單條數(shù)據(jù)。(2)批量更新同一個集合中的多條數(shù)據(jù)。修改操作也就是更新(Update)操作,對應(yīng)的MongoDB命令為“updateOne()”和“updateMany()”。這兩個命令只有以下區(qū)別,它們的參數(shù)完全一致?!駏pdateOne:只更新第1條滿足要求的數(shù)據(jù)?!駏pdateMany:更新所有滿足要求的數(shù)據(jù)。下面以“updateMany”為例來介紹更新記錄的操作。1.更新操作的語法更新操作的語法如下:updateMany的第1個參數(shù)和“find”的第1個參數(shù)完全一樣,也是一個字典,用來尋找所有需要被更新的記錄。第2個參數(shù)是一個字典,它的Key為“$set”,它的值為另一個字典。這個字典里面是需要被修改的字段名和新的值。2.舉例修改“name”為“王小六”的文檔,添加“address”字段,并把“work”字段從“廚師”改為“工程師”。更新語句見代碼3-6。代碼3-6修改name為“王小六”的文檔運行效果如圖3-49所示。圖3-49更新字段信息再次查看數(shù)據(jù)集,發(fā)現(xiàn)“王小六”的信息已經(jīng)發(fā)生了變化,如圖3-50所示。圖3-50數(shù)據(jù)發(fā)生了變化\h3.4.4實例6:刪除數(shù)據(jù)實例描述例如,要從數(shù)據(jù)集example_data_1中刪除字段“hello”值為“world”的這一條記錄。(1)從集合中刪除單條數(shù)據(jù)。(2)從集合中批量刪除多條數(shù)據(jù)。只要會查詢數(shù)據(jù),就會刪除數(shù)據(jù)。為了防止誤刪數(shù)據(jù),一般的做法是先查詢要刪除的數(shù)據(jù),然后再將查出的數(shù)據(jù)刪除。(1)查詢字段“hello”中值為“world”的這一條記錄。具體如下:db.getCollection('example_data_1').find({'hello':'world'})運行效果如圖3-51所示。圖3-51首先查詢出需要刪除的記錄(2)把查詢語句的“find”修改為“deleteOne”(如果只刪除第1條滿足要求的數(shù)據(jù)),或把查詢語句的“find”修改為“deleteMany”(如果要刪除所有滿足要求的數(shù)據(jù))。具體命令如下:db.getCollection('example_data_1').deleteMany({'hello':'world'})運行效果如圖3-52所示。圖3-52刪除數(shù)據(jù)(3)在返回的數(shù)據(jù)中,“acknowledged”為“true”表示刪除成功,“deletedCount”表示一共刪除了1條數(shù)據(jù)。(4)再次查詢example_data_1,發(fā)現(xiàn)已經(jīng)找不到被刪除的數(shù)據(jù)了,如圖3-53所示。圖3-53已經(jīng)找不到被刪除的數(shù)據(jù)了提示:慎用刪除功能。一般工程上會使用“假刪除”,即:在文檔里面增加一個字段“deleted”,如果值為0則表示沒有刪除,如果值為1則表示已經(jīng)被刪除了。默認(rèn)情況下,deleted字段的值都是0,如需要執(zhí)行刪除操作,則把這個字段的值更新為1。而查詢數(shù)據(jù)時,只查詢deleted為0的數(shù)據(jù)。這樣就實現(xiàn)了和刪除一樣的效果,即使誤操作了也可以輕易恢復(fù)。\h3.4.5實例7:數(shù)據(jù)去重實例描述在數(shù)據(jù)集example_data_1中,進行以下兩個去重操作。(1)對“age”字段去重。(2)查詢所有“age”大于等于24的數(shù)據(jù),再對“age”進行去重。去重操作用到的命令為“distinct()”。格式如下:db.getCollection('example_data_1').distinct(’字段名’,查詢語句的第一個字典)distinct()可以接收兩個參數(shù):●第1個參數(shù)為字段名,表示對哪一個字段進行去重?!竦?個參數(shù)就是查詢命令“find()”的第1個參數(shù)。distinct命令的第2個參數(shù)可以省略。1.對“age”字段去重對“age”字段去重的語句如下:db.getCollection('example_data_1').distinct('age')運行效果如圖3-54所示。圖3-54對“age”字段去重在MongoDB中返回的數(shù)據(jù)是一個數(shù)組,里面是去重以后的值。2.對滿足特定條件的數(shù)據(jù)去重首先查詢所有“age”大于等于24的數(shù)據(jù),然后對“age”進行去重。具體語句見代碼3-7。代碼3-7對“age”大于等于24的記錄的“age”字段去重運行結(jié)果如圖3-55所示。圖3-55先篩選再去重也許有讀者會問,能否去重以后再帶上其他字段呢?答案是,用“distinct()”命令不能實現(xiàn)。要實現(xiàn)這個功能,需要學(xué)習(xí)第7章的內(nèi)容。\h3.5使用Python操作MongoDB在工程中,一般都需要一種編程語言來操作數(shù)據(jù)庫。使用Python來操作數(shù)據(jù)庫有著天然的優(yōu)勢,因為Python的字典和MongoDB的文檔幾乎是一樣的格式。\h3.5.1連接數(shù)據(jù)庫1.安裝PyMongo使用Python操作MongoDB需要使用一個第三方庫——PyMongo。安裝這個庫與安裝Python其他的第三方庫一樣,使用pip安裝即可:python3-mpipinstallpymongo安裝完成以后,打開Python交互環(huán)境,導(dǎo)入PyMongo。如果不報錯(如圖3-56所示),則表示安裝成功。圖3-56不報錯表示安裝成功2.連接數(shù)據(jù)庫要使用PyMongo操作MongoDB,首先需要初始化數(shù)據(jù)庫連接。(1)如果MongoDB就運行在本地電腦上,而且也沒有修改端口或者添加用戶名和密碼,則初始化MongoClient的實例不需要帶參數(shù),直接寫為以下格式:(2)如果MongoDB運行在其他服務(wù)器上,則需要使用“URI(UniformResourceIdentifier,統(tǒng)一資源標(biāo)志符)”來指定鏈接地址。MongoDBURI的格式如下:mongodb://用戶名:密碼@服務(wù)器IP或域名:端口例如:(3)如果沒有設(shè)置權(quán)限驗證,則不需要用戶名和密碼,可以寫為:本章使用不設(shè)置密碼、不改端口、本地運行的MongoDB。3.連接庫與集合PyMongo連接庫與集合有兩種方式?!穹绞?,見代碼3-8。代碼3-8連接數(shù)據(jù)庫與集合的方法1需要注意,在使用這種方式時,代碼中的“數(shù)據(jù)庫名”和“集合名”都不是變量名,它們直接就是庫的名字和集合的名字。例如,要連接上example_data_1所在的集合,則Python代碼如下:●方式2,見代碼3-9。代碼3-9連接數(shù)據(jù)庫與集合方法2在使用這種方式時,在方括號中可以直接填變量來指定庫名和集合名。當(dāng)然,也可以直接填字符串,例如:方式1和方式2效果是完全相同的。讀者可以任意選擇一種自己喜歡的方式。方式2主要用在需要批量操作數(shù)據(jù)庫的情況下。例如在工程中,有時有多個測試環(huán)境,現(xiàn)在需要同時更新這些環(huán)境對應(yīng)的數(shù)據(jù)庫,則可以使用方式2。因為,這樣可以將多個數(shù)據(jù)庫的名字或者是多個集合的名字保存在列表中,然后再使用循環(huán)來進行操作,見代碼3-10。代碼3-10使用循環(huán)連接多個集合其中第3行代碼,在循環(huán)里面每次連接不同的庫。這樣寫可以同時更新多個數(shù)據(jù)庫的信息。對于同一個數(shù)據(jù)庫里面的多個集合,也可以使用這個方法來操作。\h3.5.2MongoDB命令在Python中的對應(yīng)方法在獲取到集合連接對象collection后,就可以用這個對象的各個方法來操作MongoDB了。雖然MongoDB的命令和collection的方法名在寫法上有微小的差異,但絕大多數(shù)的MongoDB語句的參數(shù)直接復(fù)制到Python代碼中都可以使用。MongoDB的命令使用的是駝峰命名法,而PyMongo使用的是“小寫字母加下劃線”的方式。它們的對比見表3-3。表3-3MongoDB命令與PyMongo方法對照表例如,Robo3T執(zhí)行的批量插入語句見代碼3-11。代碼3-11在Robo3T中批量插入數(shù)據(jù)對應(yīng)到Python中,見代碼3-12。代碼3-12使用Python批量插入數(shù)據(jù)其中,第4行代碼中使用了新的集合名字,用以區(qū)別。使用Python操作MongoDB還有一個好處:如果當(dāng)前使用的庫或者集合不存在,則在調(diào)用了插入方法以后,PyMongo會自動創(chuàng)建對應(yīng)的庫或集合??傊^大部分的操作,直接從Robo3T中復(fù)制到Python中都可以運行,幾乎不需要修改。\h3.5.3實例8:插入數(shù)據(jù)到MongoDB實例描述在Python中,將字典{'name':’王小六’,'age':25,'work':’廚師’}插入到MongoDB中。具體命令如下:collection.insert_one({'name':’王小六’,'age':25,'work':’廚師’})提示:PyMongo還有一個通用方法——collection.insert()。?如果傳入的是一個字典,則collection.insert()相當(dāng)于insert_one。?如果傳入的是一個包含字典的集合,則collection.insert()相當(dāng)于insert_many。但是PyMongo開發(fā)者準(zhǔn)備移除它,因此不推薦讀者在正式環(huán)境中使用這個方法。\h3.5.4實例9:從MongoDB中查詢數(shù)據(jù)實例描述在Python中,從MongoDB中查詢所有“age”大于21小于25,并且“name”不等于“夏侯小七”的記錄。具體見代碼3-13。代碼3-13在Python中查詢所有“age”大于21小于25,并且“name”不等于“夏侯小七”的記錄運行效果如圖3-57所示。圖3-57使用Python查詢MongoDB\h3.5.5實例10:更新/刪除MongoDB中的數(shù)據(jù)實例描述在Python中更新數(shù)據(jù)和刪除數(shù)據(jù):(1)對于“name”為“公孫小八”的記錄,將“age”更新為80,將“address”更新為“美國”。(2)刪除“age”為0的數(shù)據(jù)。1.更新MongoDB中的數(shù)據(jù)在Python中,可以使用udate_many方法來批量更新數(shù)據(jù),見代碼3-14。代碼3-14在Python中更新多條數(shù)據(jù)更新操作還支持一個“upsert”參數(shù)。該參數(shù)的作用是:如果數(shù)據(jù)存在,則更新;如果數(shù)據(jù)不存在,則創(chuàng)建。例如,對于“name”為“隱身人”的記錄,將“age”改為0,將“address”改為“里世界”。由于example_data_1中沒有這一條記錄,因此直接更新會報錯,如圖3-58所示。圖3-58直接更新不存在的記錄會導(dǎo)致報錯加上“upsert”參數(shù),見代碼3-15。代碼3-15在Python中更新或者插入一條數(shù)據(jù)運行效果如圖3-59所示。圖3-59運行效果提示:如果打開了更

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論