<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 挑戰全棧 MongoDB基礎視頻教程 (共21集) # [TOC] 上套課程講了Koa2,挑戰全棧就必須和數據庫打交道,個人覺的作為一個前端開發人員,操作MongoDB還是比較愜意的。因為它是一種NoSql數據庫,不用寫SQL語句,而且里邊的用法都是JSON對象的形式。所以我們在Koa2的課程中間查了MongoDB的課程,等會操作數據庫后,我們再返回去學Koa2的數據庫連接和操作,最后技術胖會帶著大家作個小實戰。 這里學的是最新的MongoDB版本,現在是3.6版本。 說明:課程每周更新2-3節,每節課12分鐘左右,因為我覺的我每次聽課只能保持12-15分鐘的注意力(一般都是早上4點起床,開始更新,比別人笨就要比別人努力),以視頻配合圖文的形式進行更新. 技術胖不是專職講師,還是一個一線程序員,所以課程中難免有錯誤和紕漏,希望小伙伴們在留言中指出,讓我們共同進步。課程參照了《MongoDB權威指南 第2版》。 ## 第01節:認識和安裝MongoDB ## 都知道MongoDB是非關系型數據庫,要了解非關系型數據庫就必須先了解關系型數據庫,關系數據庫,是建立在關系模型基礎上的數據庫。比較有名氣的關系型數據庫,比如Oracle、DB2、MSSQL、Mysql。 非關系數據庫和關系型數據庫的區別是什么? 實質:非關系型數據庫的實質:非關系型數據庫產品是傳統關系型數據庫的功能閹割版,通過減少用不到或很少用的功能,來大幅度提高產品性能。 價格:目前的非關系型數據庫基本都是免費的,而比較有名氣的關系型數據庫都是收費的,比如:Oracle、DB2、MSSQL。MySql雖然是免費的,但是處理大型數據還是要提前作很多工作的。 功能:實際開發中,很多業務需求,其實并不需要完整的關系型數據庫功能,非關系型數據庫的功能就足夠使用了。這種情況下,使用性能更高、成本更低的非關系型數據庫當然是更明智的選擇。 了解關系型數據庫和非關系型數據庫的區別后,需要有一點的取舍,比較復雜和大型的項目不建議使用非關系型數據庫,但是如果你想作個博客,CMS系統這類業務邏輯不復雜的程序,MongoDB是完全可以勝任的。 MongoDB簡介: MongoDB是一個基于分布式文件存儲的數據庫,由C++語言編寫。目的是為WEB應用提供擴展的高性能的數據存儲解決方案。MongoDB是一個介于關系型數據庫和非關系型數據庫之間的產品,是非關系型數據庫當中功能最豐富,最像關系數據庫的。他支持的數據結構非常松散,是類似json的bson格式,因此可以存儲比較復雜的數據類型。Mongo最大的特點是他支持的查詢語言非常強大,其語法有點類似于面向對象的查詢語言,幾乎可以實現類似關系數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。 安裝MongoDB: MongoDB的安裝分為Windows下的安裝和Mac的安裝(Liunx和Mac趨同)。這里我們只講解windows的安裝(別問我為什么,你們都知道的,我沒Mac電腦)。 安裝步驟: 去官網下載MongoDB,[https://www.mongodb.com/](https://www.mongodb.com/),在網站中找到Download按鈕。下載會有點忙,國外的服務器,你懂的。 下載后進行安裝,安裝沒什么難度,但是對于新手建議選擇默認安裝,而不選擇自己配置。等我們完全熟悉后再定制式配置。 安裝時如果有安全軟件,會報一些攔截,一律允許就好,不允許會安裝失敗的。 安裝完成后,需要配置“環境變量”,目的是再命令行中直接使用,而不需要輸入很長的路徑了。(此步驟觀看視頻) 運行MongoDB服務端: 安裝好MongoDB數據庫后,我們需要啟用服務端才能使用。啟用服務的命令是:`Mongod`。 打開命令行:先打開運行(快捷鍵win+R),然后輸入cmd后回車,就可以打開命令行工具。 執行mongod:在命令中直接輸入`mongod`,但是你會發現服務并沒有啟動,報了一個exception,服務停止了。 新建文件夾:出現上邊的錯誤,是因為我們沒有簡歷Mongodb需要的文件夾,一般是安裝盤的根目錄,建立`data/db`,這兩個文件夾。 運行mongod:這時候服務就可以開啟了,鏈接默認端口是27017。 鏈接服務: 服務端開啟后,我們可以使用命令行來鏈接服務端,鏈接命令是mongo。重新打開一個命令行工具,然后輸入mongo命令。也許你在鏈接時會報幾個warning(警告),我們先不用管它,以后我們再慢慢學習。 查看存在數據庫命令:`show dbs` 查看數據庫版本命令:`db.version()` 如果這兩條命令都可以正常的顯示出結果,證明我們的MongoDB數據庫已經安裝成功了,以后我們就可以愉快的開始學習了。想學習的小伙伴學完后自己動手安裝一下吧,只有自己動手才能真正學會。 ## 第02節:Mongo基本命令-1 ## 接下來的幾節直接上手Mongo命令,先讓小伙伴對MongoDB的基本命令會使用,算是快速上手。快速上手后,我們再用以后的課程把這些命令細化和升級,形成一套完整的MongoDB知識體系。小伙伴們不要著急,讓我們開始學習吧。 mongo shell 如果以前接觸過數據庫一定知道每個數據庫都有自己獨特的命令,MSSQL和MYsql用的都是Sql命令,MongoDB的操作命令就是前端最熟悉的JavaScript命令。看到這里作為前端你一定會小激動一下,這對前端來說那是極好的。 先來一個常用的賦值和輸出命令,熟悉一下。(操作前你需要打開Mongo服務器和鏈接到服務器-也就是我們上節課講的mongod命令和mongo命令)在命令行中輸入以下代碼。 ``` var x='Hello World' print(x) ``` 需要注意的是這里的輸出不再使用`console.log(‘巴拉巴拉’)`,而是使用`print(‘巴拉巴拉’)`,這個稍有區別。 還可以定義函數: ``` function jspang(){ return 'JSPang'; } ``` 學到這里,我們用的都是JavaScript的語法,這些我們可以信手拈來,非常容易。 MongoDB的存儲結構 以前我們的關系型數據庫的數據結構都是頂層是庫,庫下面是表,表下面是數據。但是MongoDB有所不同,庫下面是集合,集合下面是文件,可以看下面這張圖進行了解一下。 pic 在學習中我們可以對比記憶,這樣才能更好的了解這些名詞,其實數據表就是集合,數據行就是文件,當然這只是為了記憶,實質還是有區別的。 基礎Shell命令: 了解存儲結構后,就可以開始學習我們的基礎Shell命令了,因為這些命令比較基礎,我會以列表形式展現,具體使用方法可以到視頻中進行觀看。 * `show dbs` :顯示已有數據庫,如果你剛安裝好,會默認有local、admin(config),這是MongoDB的默認數據庫,我們在新建庫時是不允許起這些名稱的。 * `use admin`: 進入數據,也可以理解成為使用數據庫。成功會顯示:switched to db admin。 * `show collections`: 顯示數據庫中的集合(關系型中叫表,我們要逐漸熟悉)。 * `db`:顯示當前位置,也就是你當前使用的數據庫名稱,這個命令算是最常用的,因為你在作任何操作的時候都要先查看一下自己所在的庫,以免造成操作錯誤。 總結:這節課的學習已經讓我們進入了MongoDB的世界,你會感覺使用起來還是比較簡單的,都是些基本的命令,敲入回車就可以使用,但是大家還是要進行多聯系。這節課的重點是要轉變以前數據庫存儲結構的思想,掌握MongoDB的存儲結構。 ## 第03節:Mongo基本命令-2 ## 這節課繼續學習MongoDB的基礎命令,上節課我們學了一些最簡單的查看命令,比如查看數據庫,查看集合,顯示當前位置。這節課我們開始真實的操作一下數據,學會基本的數據增刪改查。直接看視頻開始學習吧。 數據操作基礎命令: * `use db(建立數據庫)`:use不僅可以進入一個數據庫,如果你敲入的庫不存在,它還可以幫你建立一個庫。但是在沒有集合前,它還是默認為空。 * `db.集合.insert( )`:新建數據集合和插入文件(數據),當集合沒有時,這時候就可以新建一個集合,并向里邊插入數據。Demo:db.user.insert({“name”:”jspang”}) *` db.集合.find( )`:查詢所有數據,這條命令會列出集合下的所有數據,可以看到MongoDB是自動給我們加入了索引值的。Demo:db.user.find() * `db.集合.findOne( )`:查詢第一個文件數據,這里需要注意的,所有MongoDB的組合單詞都使用首字母小寫的駝峰式寫法。 * `db.集合.update({查詢},{修改})`:修改文件數據,第一個是查詢條件,第二個是要修改成的值。這里注意的是可以多加文件數據項的,比如下面的例子。 ``` db.jspang.update({"name":"jspang"},{"name":"jspang","age":"32"}) ``` * `db.集合.remove(條件)`:刪除文件數據,注意的是要跟一個條件。 ``` Demo:db.user.remove({“name”:”jspang”}) ``` * `db.集合.drop( )`:刪除整個集合,這個在實際工作中一定要謹慎使用,如果是程序,一定要二次確認。 * `db.dropDatabase( )`:刪除整個數據庫,在刪除庫時,一定要先進入數據庫,然后再刪除。實際工作中這個基本不用,實際工作可定需要保留數據和痕跡的。 總結:這節課都是對數據或者庫的操作,這些雖然簡單,但是你每天都要用到,所以建議反復練習,增強記憶。 ## 第04節:用js文件寫mongo命令 ## 在命令行中寫mongo的命令(shell)實在是太麻煩了(反正技術胖是無法忍受windows系統的這種命令行的),急需一種更好的方式來進行工作,這節課我們就學一下用JS文件來寫shell命令和執行。在JS里寫mongo的Shell命令大部分是相同的,只有小部分不一樣。 把命令寫入JS中: 現在模擬一個用戶登錄日志表的信息,用JS進行編寫。新在一個新建的目錄下,比如D:/mongoShell/,新建一個goTask.js文件。文件內容如下: goTask.js文件 ``` var userName="jspang"; //聲明一個登錄名 var timeStamp=Date.parse(new Date()); //聲明登錄時的時間戳 var jsonDdatabase={"loginUnser":userName,"loginTime":timeStamp}; //組成JSON字符串 var db = connect('log'); //鏈接數據庫 db.login.insert(jsonDdatabase); //插入數據 print('[demo]log print success'); //沒有錯誤顯示成功 ``` 如果上邊這個基礎的代碼你看起來還不是那么容易,那我建議你先停下這門課的學習,去學一下JS的基礎知識,只有基礎打牢了,學習起來才會快速。 執行JS文件 寫好了JS文件,需要執行起來,看一下文件是否存在問題,能否順利的插入數據到MongoDB中。 執行其實很簡單,只要使用mongo xxx.js(xxx就是我們寫的goTask.js文件)。 ``` mongo goTask.js ``` 然后我們可以在命令行看到已經執行成功,可以到終端中進行查看插入結果。 總結:這節課很好的解決了在終端中寫命令行的難題,雖然大部分Shell和在命令行中寫法一樣,但是也稍有不同,希望小伙伴們可以輕松掌握。 ## 第05節:批量插入的正確方法 ## 前4節課,我們都是簡單講解了MongoDB的使用方法,目的是快速入門。從這節課開始,我們要詳細深入的講解MongoDB的各項操作,難度也開始逐漸提高。需要提示如果前邊的課程還沒有聯系熟練,那先練習一下,否則接下來學習會稍有困難。 在操作數據庫時要注意兩個能力: 1. 第一個是快速存儲能力。 2. 第二個是方便迅速查詢能力。 批量插入: 批量數據插入是以數組的方式進行的(如果寫錯,可以3個回車可以切出來)。我們現在命令行中敲入下面的代碼,我們可以看到數據順利插入了。 ``` db.test.insert([ {"_id":1}, {"_id":2}, {"_id":3} ]) ``` 老版本MongoDB(3.2以前的版本基本都需要)是需要在Insert前加一個batch單詞的,如下代碼。 ``` db.test.batchInsert([ {"_id":1}, {"_id":2}, {"_id":3} ]) ``` 注意一次插入不要超過48M,向.zip和大圖片什么的盡量用靜態存儲,MongoDB存儲靜態路徑就好,這也算是一個規則。 批量插入性能測試 剛學了批量插入,那是循環插入快?還是批量插入快那?在一般人的認知里肯定是批量插入更快(其實這毋庸置疑),但我們要拿出極客精神,探個究竟,試著寫一個小Shell,來驗證一下結果。 先寫一個循環插入方法: ``` var startTime = (new Date()).getTime(); //得到開始時間 var db = connect('log'); //鏈接數據庫 //開始循環 for(let i=0;i<1000;i++){ db.test.insert({num:i}); } var runTime = (new Date()).getTime()-startTime;//計算時間差 print ('This run this is:'+runTime+'ms');//打印出來 ``` 我測試的時間507ms,這個速度雖然和電腦性能有關,但還是不太理想,1000條數據用了將近半秒,組長會發飆的。 批量插入代碼: ``` var startTime = (new Date()).getTime(); var db = connect('log'); var tempArray = [] //聲明一個數組 for(let i=0;i<1000;i++){ //循環向數組中放入值 tempArray.push({num:i}); } db.test.insert(tempArray) //批量一次插入 var runTime = (new Date()).getTime()-startTime; print ('This run this is:'+runTime+'ms'); ``` 這次用了17ms,性能遠遠超過循環插入。 總結:在工作中一定要照顧數據庫性能,這也是你水平的提現,一個技術會了很簡單,但是要作精通不那么簡單。學完這節,記得在工作中如果在循環插入和批量插入舉起不定,那就選批量插入吧,它會給我們更優的性能體驗。 ## 第06節:修改:Update常見錯誤 ## 這節課開始我們要說一說Update的詳細操作,我們先來看一下常見錯誤,我們知道了困難或者說問題在哪里,我們再提出解決方案。這節課我會先演示一些錯誤的Update方法,然后再說正確的方法。希望不要誤導小伙伴。 錯誤1:只update修改項 如果你有過關系型數據庫的經驗,你會很容易犯只修改需要改變的一項,因為在關系型數據庫中就是這樣作的。先來準備一些數據,這些數據模擬了一個軟件開發小組的組成(當然這不能當真)。 ``` var workmate1={ name:'JSPang', age:33, sex:1, job:'前端', skill:{ skillOne:'HTML+CSS', SkillTwo:'JavaScript', SkillThree:'PHP' }, regeditTime:new Date() } var workmate2={ name:'ShengLei', age:30, sex:1, job:'JAVA后端', skill:{ skillOne:'HTML+CSS', SkillTwo:'J2EE', SkillThree:'PPT' }, regeditTime:new Date() } var workmate3={ name:'MinJie', age:20, sex:1, job:'UI設計', skill:{ skillOne:'PhotoShop', SkillTwo:'UI', SkillThree:'Word+Excel+PPT' }, regeditTime:new Date() } var db=connect('company') var workmateArray=[workmate1,workmate2,workmate3] db.workmate.insert(workmateArray) print('[SUCCESS]: The data was inserted successfully.'); ``` 上面的代碼,我們以文件的形式向數據庫中插入了3條數據。 這時候我突然發現UI職位的性別出現了錯誤,本來人家是個美女,這里缺寫成了男,我們需要修改這條數據,但是經常會這樣寫。 這樣寫的問題是,我們的最后一條數據變成了只有sex:0,其它數據全部丟失了,這肯定不是我們想要的。這是新手在操作數據庫修改時經常犯的一個錯誤,就是只修改變動的數據。 正確修改方法: 可以聲明一個變量,然后把要改變數據的全部信息放入變量,最后執行修改操作。 ``` var db=connect('company') var workmate3={ name:'MinJie', age:20, sex:0, job:'UI設計', skill:{ skillOne:'PhotoShop', SkillTwo:'UI', SkillThree:'Word+Excel+PPT' }, regeditTime:new Date() } db.workmate.update({name:'MinJie'},workmate3) print('[update]: The data was updated successfully'); ``` 這時候你需要刪除(db.workmate.drop())表中的數據,因為MinJie這個用戶已經不在數據庫中了,然后重新使用load方法載入插入數據再進行修改。 //執行命令如下: ``` db.workmate.drop() load('./demo02.js') load('./demo03.js') ``` 現在這種方法才是正確的,數據修改正常了,但是你會發現寫起來非常麻煩,而且特別容易寫錯。下節課我們會介紹update修改器,可以很好的解決這個問題。 ## 第07節:修改:初識update修改器 ## 上節課的修改用起來實在是不夠優雅,這是我們一個偉大的前端不能接受的,所以我們要學習新知識update修改器,來解決這個問題。update修改器可以幫助我們快速和簡單的修改數據,讓我們的操作更簡單方便。 $set修改器 用來修改一個指定的鍵值(key),這時候我們要修改上節課的sex和age就非常方便了,只要一句話就可以搞定。 ``` dbd .workmate.update({"name":"MinJie"},{"$set":{sex:2,age:21}}) ``` 修改好后,我們可以用`db.workmate.find()`來進行查看,你會發現數據已經被修改。 修改嵌套內容(內嵌文檔) 比如現在的UI的技能發生了變化,說她不會作PPT而是word作的很好,需要進行修改。這時候你會發現skill數據是內嵌的,這時候我們可以屬性的形式進行修改,skill.skillThree。具體看下面的代碼。 ``` db.workmate.update({"name":"MinJie"},{"$set":{"skill.skillThree":'word'}}) ``` 這樣就可以簡單的修改內嵌文檔了。 $unset用于將key刪除 它的作用其實就是刪除一個key值和鍵。一般女孩子都是不希望看到自己的年齡的,所以要求我們把年齡刪除。這時候我們就可以使用$unset的形式。 ``` db.workmate.update({"name":"MinJie"},{$unset:{"age":''}}) ``` 當你刪除后,想加回來可以直接用set進行添加。 $inc對數字進行計算 它是對value值的修改,但是修改的必須是數字,字符串是不起效果的。我們現在要對MiJie的年齡減去2歲,就可以直接用$inc來操作。 ``` db.workmate.update({"name":"MinJie"},{$inc:{"age":-2}}) ``` multi選項 現在領導說了,你要把每個人的愛好也加入進來,但是如果你直接寫會只加一個,比如下面這種形式。 ``` db.workmate.update({},{$set:{interset:[]}}) ``` 這時候你用db.workmate.find()查找,你會發現只改變了第一個數據,其他兩條沒有改變。這時候我們想改變就要用到multi選項。 ``` db.workmate.update({},{$set:{interset:[]}},{multi:true}) ``` 這時候每個數據都發生了改變,multi是有ture和false兩個值,true代表全部修改,false代表只修改一個(默認值) upsert選項 upsert是在找不到值的情況下,直接插入這條數據。比如我們這時候又來了一個新同事xiaoWang,我們這時候修改他的信息,age設置成20歲,但集合中并沒有這條數據。這時候可以使用upsert選項直接添加。 ``` db.workmate.update({name:'xiaoWang'},{$set:{age:20}},{upsert:true}) ``` upsert也有兩個值:true代表沒有就添加,false代表沒有不添加(默認值)。 總結:這節課的內容非常多,主要學習了update修改器有關的一些東西。一定要課下多練習幾遍,否則很快就會忘記的。 ## 第08節:修改:update數組修改器 ## 已經會了一些基礎的修改器,這節課我們主要學習一下數組修改器的操作,當然也可以修改內嵌文檔,也就是對象形式的數據。讓我們努力學習吧。 $push追加數組/內嵌文檔值 $push的功能是追加數組中的值,但我們也經常用它操作內嵌穩文檔,就是{}對象型的值。先看一個追加數組值的方式,比如我們要給小王加上一個愛好(interset)為畫畫(draw): db.workmate.update({name:'xiaoWang'},{$push:{interest:'draw'}}) 當然$push修飾符還可以為內嵌文檔增加值,比如我們現在要給我們的UI,增加一項新的技能skillFour為draw,這時候我們可以操作為: db.workmate.update({name:'MinJie'},{$push:{"skill.skillFour":'draw'}}) $push修飾符在工作中是最常用的,因為我們的數據一般都會涉及數組和內嵌文檔的操作,一定要掌握。 $ne查找是否存在 它主要的作用是,檢查一個值是否存在,如果不存在再執行操作,存在就不執行,這個很容易弄反,記得我剛學的時候就經常弄反這個修改器的作用,給自己增加了很多坑。 例子:如果xiaoWang的愛好(interest)里沒有palyGame這個值,我們就加入Game這個愛好。 db.workmate.update({name:'xiaoWang',"interest":{$ne:'playGame'}},{$push:{interest:'Game'}}) 總結:沒有則修改,有則不修改。 $addToSet 升級版的$ne 它是$ne的升級版本(查找是否存在,不存在就push上去),操作起來更直觀和方便,所以再工作中這個要比$en用的多。 例子:我們現在要查看小王(xiaoWang)興趣(interest)中有沒有閱讀(readBook)這項,沒有則加入讀書(readBook)的興趣. db.workmate.update({name:"xiaoWang"},{$addToSet:{interest:"readBook"}}) $each 批量追加 它可以傳入一個數組,一次增加多個值進去,相當于批量操作,性能同樣比循環操作要好很多,這個是需要我們注意的,工作中也要先組合成數組,然后用批量的形式進行操作。 例子:我們現在要給xiaoWang,一次加入三個愛好,唱歌(Sing),跳舞(Dance),編碼(Code)。 var newInterset=["Sing","Dance","Code"]; db.workmate.update({name:"xiaoWang"},{$addToSet:{interest:{$each:newInterset}}}) $pop 刪除數組值 $pop只刪除一次,并不是刪除所有數組中的值。而且它有兩個選項,一個是1和-1。 1:從數組末端進行刪除 -1:從數組開端進行刪除 例子:現在要刪除xiaoWang的編碼愛好(code)。 db.workmate.update({name:'xiaoWang'},{$pop:{interest:1}}) 數組定位修改 有時候只知道修改數組的第幾位,但并不知道是什么,這時候我們可以使用interest.int 的形式。 例子,比如我們現在要修改xiaoWang的第三個興趣為編碼(Code),注意這里的計數是從0開始的。 db.workmate.update({name:'xiaoWang'},{$set:{"interest.2":"Code"}}) 總結:這節課主要講了于數組和內嵌文檔有關的update修改器,內容很多,都需要不斷熟練記憶。當然如果你記不住,你至少記住這個博客網址,因為技術胖把筆記已經給你整理好了。 ## 第09節:修改:狀態返回與安全 ## 在操作數據庫時,對數據的修改是需要有足夠的安全措施的,其實在實際工作中,我們用db.collections.update的時候不多,在修改時我們都會用findAndModify,它可以給我們返回來一些必要的參數,讓我們對修改多了很多控制力,控制力的加強也就是對安全的強化能力加強了。 應答式寫入: 在動手學習代碼之前,我們先來了解一個概念:應答式寫入。在以前的文章中,我們的操作都是非應答式寫入,就是在操作完數據庫后,它并沒有給我們任何的回應和返回值,而是我們自己安慰自己寫了一句話(print(‘[update]:The data was updated successfully’);)。這在工作中是不允許的,因為根本不能提現我們修改的結果。 應答式寫入就會給我們直接返回結果(報表),結果里邊的包含項會很多,這樣我們就可以很好的進行程序的控制和安全機制的處理。有點像前端調用后端接口,無論作什么,后端都要給我一些狀態字一樣。 db.runCommand( ): 它是數據庫運行命令的執行器,執行命令首選就要使用它,因為它在Shell和驅動程序間提供了一致的接口。(幾乎操作數據庫的所有操作,都可以使用runCommand來執行)現在我們試著用runCommand來修改數據庫,看看結果和直接用db.collections.update有什么不同。 db.workmate.update({sex:1},{$set:{money:1000}},false,true) var resultMessage=db.runCommand({getLastError:1}) printjson(resultMessage); 上邊的代碼,我們修改了所有男士的數據,每個人增加了1000元錢(money),然后用db.runCommand()執行,可以看到執行結果在控制臺返回了。 { "connectionId" : 1, "updatedExisting" : true, "n" : 2, "syncMillis" : 0, "writtenTo" : null, "err" : null, "ok" : 1 } false:第一句末尾的false是upsert的簡寫,代表沒有此條數據時不增加; true:true是multi的簡寫,代表修改所有,這兩個我們在前邊課程已經學過。 getLastError:1 :表示返回功能錯誤,這里的參數很多,如果有興趣請自行查找學習,這里不作過多介紹。 printjson:表示以json對象的格式輸出到控制臺。 db.listCommands( ):查看所有的Commad命令,內容很多,本套課程只講解工作中經常使用的內容。 比如我們要查看是否和數據庫鏈接成功了,就可以使用Command命令。 db.runCommand({ping:1}) 返回ok:1就代表鏈接正常。 findAndModify: 從名字上就可以看出,findAndModify是查找并修改的意思。配置它可以在修改后給我們返回修改的結果。我們先看下面的代碼: var myModify={ findAndModify:"workmate", query:{name:'JSPang'}, update:{$set:{age:18}}, new:true //更新完成,需要查看結果,如果為false不進行查看結果 } var ResultMessage=db.runCommand(myModify); printjson(ResultMessage) findAndModify的性能是沒有直接使用db.collections.update的性能好,但是在實際工作中都是使用它,畢竟要商用的程序安全性還是比較重要的。 findAndModify屬性值: query:需要查詢的條件/文檔 sort: 進行排序 remove:[boolean]是否刪除查找到的文檔,值填寫true,可以刪除。 new:[boolean]返回更新前的文檔還是更新后的文檔。 fields:需要返回的字段 upsert:沒有這個值是否增加。 總結:這節課講了一些跟安全有關的操作,但這不是全部,我們隨著課程的深入還會繼續學習更多的知識。工作中盡量使用findAndModify來進行更新數據,這樣會更安全和直觀,這點性能的損失是值得的。 ## 第10節:查詢:find的不等修飾符 ## MongoDB的查找操作我們會分幾節課來講,因為內容還是比較多的,而且在開發中查找是應用最多的操作,幾乎每個模塊都會用到,所以查找的部分將是本套課的重中之重。這節課我們先來看看簡單的查詢條件,也了解一下find基礎用法。如果你以前操作過關系型數據庫,比如MySql,你會對>大于),<(小于),=(等于)這些東西很熟悉,但是非關系型數據庫不能直接使用這些符號,稍有區別。 構造數據: 我們需要構造更多的數據到集合中,這樣我們才能很好的講解查詢條件,下面代碼你可以直接復制進行添加。當然你也可以自己隨意加一些數據到集合中,只要方便我們學習就可以了。 var workmate1={ name:'JSPang', age:33, sex:1, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', skillThree:'PHP' }, regeditTime:new Date(), interest:[] } var workmate2={ name:'ShengLei', age:31, sex:1, job:'JAVA后端', skill:{ skillOne:'HTML+CSS', skillTwo:'J2EE', skillThree:'PPT' }, regeditTime:new Date(), interest:[] } var workmate3={ name:'MinJie', age:18, sex:0, job:'UI', skill:{ skillOne:'PhotoShop', skillTwo:'UI', skillThree:'PPT' }, regeditTime:new Date(), interest:[] } var workmate4={ name:'XiaoWang', age:25, sex:1, job:'UI', skill:{ skillOne:'PhotoShop', skillTwo:'UI', skillThree:'PPT' }, regeditTime:new Date(), interest:[] } var workmate5={ name:'LiangPeng', age:28, sex:1, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', }, regeditTime:new Date(), interest:[] } var workmate6={ name:'HouFei', age:25, sex:0, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', }, regeditTime:new Date(), interest:[] } var workmate7={ name:'LiuYan', age:35, sex:0, job:'美工', skill:{ skillOne:'PhotoShop', skillTwo:'CAD', }, regeditTime:new Date(), interest:[] } var workmate8={ name:'DingLu', age:20, sex:0, job:'美工', skill:{ skillOne:'PhotoShop', skillTwo:'CAD', }, regeditTime:new Date(), interest:[] } var workmate9={ name:'JiaPeng', age:29, sex:1, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', skillThree:'PHP' }, regeditTime:new Date(), interest:[] } var workmate10={ name:'LiJia', age:26, sex:0, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', skillThree:'PHP' }, regeditTime:new Date(), interest:[] } var db=connect('company'); var workmateArray=[workmate1,workmate2,workmate3,workmate4,workmate5,workmate6,workmate7,workmate8,workmate9,workmate10]; db.workmate.insert(workmateArray); print('[SUCCESS]:The data was inserted successfully'); 簡單查找: 比如我們現在要查找數據中技能一會HTML+CSS的所有人。那我們直接進行查找加條件就可以了。 db.workmate.find({"skill.skillOne":"HTML+CSS"}) 這時候我們不能使用load來載入了,以后我會給大家講使用的方法,這里先用比較笨的方法,使用粘貼復制的方法執行。 篩選字段 現在返回來的數據項太多,太亂,有時候我們的程序并不需要這么多選項。比如我們只需要姓名和技能就可以了。這時候我們需要寫第二個參數,看下面的代碼。 db.workmate.find( {"skill.skillOne":"HTML+CSS"}, {name:true,"skill.skillOne":true} ) 你會在終端中看到如下結果: { "_id" : ObjectId("5a611350c4e36dee6008987a"), "name" : "JSPang", "skill" : { "skillOne" : "HTML+CSS" } } { "_id" : ObjectId("5a611350c4e36dee6008987b"), "name" : "ShengLei", "skill" : { "skillOne" : "HTML+CSS" } } { "_id" : ObjectId("5a611350c4e36dee6008987e"), "name" : "LiangPeng", "skill" : { "skillOne" : "HTML+CSS" } } { "_id" : ObjectId("5a611350c4e36dee6008987f"), "name" : "HouFei", "skill" : { "skillOne" : "HTML+CSS" } } { "_id" : ObjectId("5a611350c4e36dee60089882"), "name" : "JiaPeng", "skill" : { "skillOne" : "HTML+CSS" } } { "_id" : ObjectId("5a611350c4e36dee60089883"), "name" : "LiJia", "skill" : { "skillOne" : "HTML+CSS" } } 細心的小伙伴會發現還不夠完美,多了一個ID字段,這個也不是我們想要的,這時候只要把_id:false就可以了。當然這里的false和true,也可以用0和1表示。 db.workmate.find( {"skill.skillOne":"HTML+CSS"}, {name:true,"skill.skillOne":true,_id:false} ) 這時候你在終端中查看結果,已經是我們想要的了。 { "name" : "JSPang", "skill" : { "skillOne" : "HTML+CSS" } } { "name" : "ShengLei", "skill" : { "skillOne" : "HTML+CSS" } } { "name" : "LiangPeng", "skill" : { "skillOne" : "HTML+CSS" } } { "name" : "HouFei", "skill" : { "skillOne" : "HTML+CSS" } } { "name" : "JiaPeng", "skill" : { "skillOne" : "HTML+CSS" } } { "name" : "LiJia", "skill" : { "skillOne" : "HTML+CSS" } } 其實這些查找操作,都是在作等于的階段,但是不光只有等于查詢,我們需要更多的查詢條件。 不等修飾符 小于($lt):英文全稱less-than 小于等于($lte):英文全稱less-than-equal 大于($gt):英文全稱greater-than 大于等于($gte):英文全稱greater-than-equal 不等于($ne):英文全稱not-equal 我們現在要查找一下,公司內年齡小于30大于25歲的人員。看下面的代碼。 db.workmate.find( {age:{$lte:30,$gte:25}}, {name:true,age:true,"skill.skillOne":true,_id:false} ) 日期查找 MongoDB也提供了方便的日期查找方法,現在我們要查找注冊日期大于2018年1月10日的數據,我們可以這樣寫代碼。 var startDate= new Date('01/01/2018'); db.workmate.find( {regeditTime:{$gt:startDate}}, {name:true,age:true,"skill.skillOne":true,_id:false} ) 我們先生命了一個日期變量,然后把使用大于符進行篩選。 總結:這節課內容并不多,但如果你是個DBA(數據庫管理員)工作中每天都會用到,所以這節課的內容練習是必須的,如果你懶得動手,那接下來的課程你可能無法學會。 ## 第11節:查詢:find的多條件查詢 ## 很多時候我們需要查詢的值不只是有一個簡單的條件,比如我們現在要查詢一下同事中是33歲和25歲的,還比如我們要查詢同事中大于30歲并且會PHP技能的。MongoDB在這方面也支持的很好,我們來學習一下。 $in修飾符 in修飾符可以輕松解決一鍵多值的查詢情況。就如上面我們講的例子,現在要查詢同事中年齡是25歲和33歲的信息。 db.workmate.find({age:{$in:[25,33]}}, {name:1,"skill.skillOne":1,age:1,_id:0} ) 于$in相對的修飾符是$nin,就是查詢除了$in條件以為的指,小伙伴們可以自己進行練習一下,這里我就不作過多的演示了。 $or修飾符 它用來查詢多個鍵值的情況,就比如查詢同事中大于30歲或者會做PHP的信息。主要區別是兩個Key值。$in修飾符是一個Key值,這個需要去比較記憶。 db.workmate.find({$or:[ {age:{$gte:30}}, {"skill.skillThree":'PHP'} ]}, {name:1,"skill.skillThree":1,age:1,_id:0} ) or很好理解,就是或者的意思,我們查出來的結果也是一樣的,查出了年齡大于30歲的,或者會做PHP的信息。相對應的還有$nor修飾符,這里不作演示了,自己試驗一下。 $and修飾符 $and用來查找幾個key值都滿足的情況,比如要查詢同事中大于30歲并且會做PHP的信息,這時需要注意的是這兩項必須全部滿足。當然寫法還是比較簡單的。只要把上面代碼中的or換成and就可以了。 db.workmate.find({$and:[ {age:{$gte:30}}, {"skill.skillThree":'PHP'} ]}, {name:1,"skill.skillThree":1,age:1,_id:0} ) $not修飾符 它用來查詢除條件之外的值,比如我們現在要查找除年齡大于20歲,小于30歲的人員信息。需要注意的是$not修飾符不能應用在條件語句中,只能在外邊進行查詢使用。 db.workmate.find({ age:{ $not:{ $lte:30, $gte:20 } } }, {name:1,"skill.skillOne":1,age:1,_id:0} ) 總結:這節課的知識比較簡單,但是要區分記憶,很容易搞混。幸運的是這里已經為你準備好了學習筆記。當你忘記的時候過來看看吧。 ## 第12節:查詢:find的數組查詢 ## 這節主要學習數組的查詢,在學習update時就花了重墨去講數組的操作,可見數組的操作在MongoDB中很受重視,因為稍微大型一點的項目,設計的數據集合都復雜一些,都會涉及數組的操作。 完善數據 以前的我們的workmate集合對數組涉及還很少,現在在數據中加入了興趣(interest),并且給每個人加入了一些興趣,比如有寫代碼,做飯,看電影….. 當然這些數據你可以自己隨意構建,但是如果你不想自己費事費腦,這里也為你準備好了數據,你只要把以前的表刪除(drop)掉,重新載入(load)就可以了。 var workmate1={ name:'JSPang', age:33, sex:1, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', skillThree:'PHP' }, regeditTime:new Date(), interest:['看電影','看書','吃美食','釣魚','旅游'] } var workmate2={ name:'ShengLei', age:31, sex:1, job:'JAVA后端', skill:{ skillOne:'HTML+CSS', skillTwo:'J2EE', skillThree:'PPT' }, regeditTime:new Date(), interest:['籃球','看電影','做飯'] } var workmate3={ name:'MinJie', age:18, sex:0, job:'UI', skill:{ skillOne:'PhotoShop', skillTwo:'UI', skillThree:'PPT' }, regeditTime:new Date(), interest:['做飯','畫畫','看電影'] } var workmate4={ name:'XiaoWang', age:25, sex:1, job:'UI', skill:{ skillOne:'PhotoShop', skillTwo:'UI', skillThree:'PPT' }, regeditTime:new Date(), interest:['寫代碼','籃球','畫畫'] } var workmate5={ name:'LiangPeng', age:28, sex:1, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', }, regeditTime:new Date(), interest:['玩游戲','寫代碼','做飯'] } var workmate6={ name:'HouFei', age:25, sex:0, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', }, regeditTime:new Date(), interest:['化妝','讀書','做飯'] } var workmate7={ name:'LiuYan', age:35, sex:0, job:'美工', skill:{ skillOne:'PhotoShop', skillTwo:'CAD', }, regeditTime:new Date(), interest:['畫畫','聚會','看電影'] } var workmate8={ name:'DingLu', age:20, sex:0, job:'美工', skill:{ skillOne:'PhotoShop', skillTwo:'CAD', }, regeditTime:new Date(), interest:['美食','看電影','做飯'] } var workmate9={ name:'JiaPeng', age:29, sex:1, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', skillThree:'PHP' }, regeditTime:new Date(), interest:['寫代碼','籃球','游泳'] } var workmate10={ name:'LiJia', age:26, sex:0, job:'前端', skill:{ skillOne:'HTML+CSS', skillTwo:'JavaScript', skillThree:'PHP' }, regeditTime:new Date(), interest:['玩游戲','美食','籃球'] } var db=connect('company'); var workmateArray=[workmate1,workmate2,workmate3,workmate4,workmate5,workmate6,workmate7,workmate8,workmate9,workmate10]; db.workmate.insert(workmateArray); print('[SUCCESS]:The data was inserted successfully'); 基本數組查詢 比如現在我們知道了一個人的愛好是’畫畫’,’聚會’,’看電影’,但我們不知道是誰,這時候我們就可以使用最簡單的數組查詢(實際工作中,這種情況基本不常用,所以這種查詢只作知識點儲備就可以了)。 db.workmate.find({interest:['畫畫','聚會','看電影']}, {name:1,interest:1,age:1,_id:0} ) 在終端中運行后,我們得到了數據。這時候我們說,想查出看興趣中有看電影的員工信息。按照正常邏輯,應該使用下面的代碼。 db.workmate.find({interest:['看電影']}, {name:1,interest:1,age:1,_id:0} ) 運行后,并沒有如我們所愿得到相應的人員數據,數據為空。那問題出現在哪里?問題就在于我們寫了一個中括號([]),因為加上中括號就相當于完全匹配了,所以沒有得到一條符合查詢條件的數據。我們去掉中括號再看看結果。 db.workmate.find({interest:'看電影'}, {name:1,interest:1,age:1,_id:0} ) 這就是我們在數組中查詢一項的方法,這也是數組查詢的最簡單用法。 $all-數組多項查詢 現在我們的條件升級了,要查詢出喜歡看電影和看書的人員信息,也就是對數組中的對象進行查詢,這時候要用到一個新的查詢修飾符$all。看下面的例子: db.workmate.find( {interest:{$all:["看電影","看書"]}}, {name:1,interest:1,age:1,_id:0} ) 這時候找到了興趣中既有看電影又有看書的人員。 $in-數組的或者查詢 用$all修飾符,是需要滿足所有條件的,$in主要滿足數組中的一項就可以被查出來(有時候會跟$or弄混)。比如現在要查詢愛好中有看電影的或者看書的員工信息。 db.workmate.find( {interest:{$in:["看電影","看書"]}}, {name:1,interest:1,age:1,_id:0} ) $size-數組個數查詢 $size修飾符可以根據數組的數量查詢出結果。比如現在我們要查找興趣的數量是5個人員信息,這時候就可以使用$size。 db.workmate.find( {interest:{$size:5}}, {name:1,interest:1,age:1,_id:0} ) 這時候是5項愛好的人員就會顯示出來了。 $slice-顯示選項 有時候我并不需要顯示出數組中的所有值,而是只顯示前兩項,比如我們現在想顯示每個人興趣的前兩項,而不是把每個人所有的興趣都顯示出來。 db.workmate.find( {}, {name:1,interest:{$slice:2},age:1,_id:0} ) 這時候就顯示出了每個人興趣的前兩項,如果我們想顯示興趣的最后一項,可以直接使用slice:-1,來進行查詢。 db.workmate.find( {}, {name:1,interest:{$slice:-1},age:1,_id:0} ) 總結:如果你只看視頻一定學不會,程序這東西必須要動手練習,我在所有的視頻中都反復強調,目的沒有別的就是想讓你們真的學會,并應用到工作中去。 ## 第13節:查詢:find的參數使用方法 ## 前邊已經講了3節查詢,都是在操作find方法的第一個參數(query)和第二個參數(fields)。find還有幾個常用的參數,這些參數多用在分頁和排序上。這節我們就把這些常用的選項說一說,理解后我們演示一個分頁的效果。 find參數: query:這個就是查詢條件,MongoDB默認的第一個參數。 fields:(返回內容)查詢出來后顯示的結果樣式,可以用true和false控制是否顯示。 limit:返回的數量,后邊跟數字,控制每次查詢返回的結果數量。 skip:跳過多少個顯示,和limit結合可以實現分頁。 sort:排序方式,從小到大排序使用1,從大到小排序使用-1。 分頁Demo: 明白了上面這些選項,現在可以作一個最簡單的分頁,我們把同事集合(collections)進行分頁,每頁顯示兩個,并且按照年齡從小到大的順序排列。 dbd .workmate.find({},{name:true,age:true,_id:false}).limit(0).skip(2).sort({age:1}); $where修飾符 它是一個非常強大的修飾符,但強大的背后也意味著有風險存在。它可以讓我們在條件里使用javascript的方法來進行復雜查詢。我們先來看一個最簡單的例子,現在要查詢年齡大于30歲的人員。 db.workmate.find( {$where:"this.age>30"}, {name:true,age:true,_id:false} ) 這里的this指向的是workmate(查詢集合)本身。這樣我們就可以在程序中隨意調用。雖然強大和靈活,但是這種查詢對于數據庫的壓力和安全性都會變重,所以在工作中盡量減少$where修飾符的使用。 ## 第14節:查詢:find如何在js文本中使用 ## 前邊使用find都是JS在文本中寫完,然后復制到終端中執行,這樣非常麻煩。在講的過程中已經有很多小伙伴在問我如何像寫update語句一樣,在文本中直接運行。這節課我們就學習一下如何直接在文本中執行。 hasNext循環結果 想在文本中執行我們的find語句要用到游標和循環的操作,先看一下代碼,代碼中我已經對每一句進行了注釋。 var db = connect("company") //進行鏈接對應的集合collections var result = db.workmate.find() //聲明變量result,并把查詢結果賦值給result //利用游標的hasNext()進行循環輸出結果。 while(result.hasNext()){ printjson(result.next()) //用json格式打印結果 } 寫完后,現在你只需要在終端中進行load()就可以執行了,再也不用麻煩的復制粘貼了。 forEach循環 利用hasNext循環結果,需要借助while的幫助,MongoDB也為我們提供了forEach循環,現在修改上邊的代碼,使用forEach循環來輸出結果。 var db = connect("company") //進行鏈接對應的集合collections var result = db.workmate.find() //聲明變量result,并把查詢結果賦值給result //利用游標的hasNext()進行循環輸出結果。 result.forEach(function(result){ printjson(result) }) 作為個人覺的forEach循環更為優雅。這兩種方法都是非常不錯的,憑借自己愛好進行選擇吧。 總結:那我們MongoDB的基礎部分就全部講完了,我們學會了它的增、刪、改、查,你也可以使用MongoDB進行一些操作了。需要注意的是,只是這篇文章的完結,下篇文章我們進行講解MongoDB,開始講解MongoDB的索引。 ## 第15節:索引:構造百萬級數據 ## 索引的性能提現必須要有大量數據才能看出來,你說你有10條20條數據,這是根本看不出來效果的,這節課就通過隨機數的方法,創造出一個百萬級數據的數據庫出來。(建議收看視頻學習)。 安裝Node 為了課程調試代碼方便,我們安裝Node,用來在終端中執行js,查看結果。 Node下載地址:https://nodejs.org/en/ (直接下載LTS版本就可以了) 安裝非常簡單,只要會安裝QQ,就應該可以安裝上,一直下一步也是沒有問題的。安裝好后,是不用配置我們的環境變量的。 我們可以在終端中輸入 node -v 來查看是否安裝成功,出現版本號就是安裝成功。 制作隨機數方法: 我們要想生成一個百萬級的數據集合,必須要有隨機數的參與,我們需要寫一個隨機數的方法。下面的代碼,創建了一個隨機數方法。 //生成隨機數 function GetRandomNum(min,max){ let range = max-min; //得到隨機數區間 let rand = Math.random(); //得到隨機值 return (min + Math.round(rand *range)); //最小值+隨機數取整 } console.log(GetRandomNum(10000,99999)); 制作隨機用戶名: 有了隨機數的方法,我們就可以制作一個隨機生成的用戶名。目的是存在不同的用戶名,方便我們測試查詢速度。 //生成隨機數 function GetRandomNum(min,max){ let range = max-min; //得到隨機數區間 let rand = Math.random(); //得到隨機值 return (min + Math.round(rand *range)); //最小值+隨機數取整 } //console.log(GetRandomNum(10000,99999)); //生成隨機用戶名 function GetRadomUserName(min,max){ let tempStringArray= "123456789qwertyuiopasdfghjklzxcvbnm".split("");//構造生成時的字母庫數組 let outPuttext = ""; //最后輸出的變量 //進行循環,隨機生產用戶名的長度,這里需要生成隨機數方法的配合 for(let i=1 ;i<GetRandomNum(min,max);i++){ //隨機抽取字母,拼裝成需要的用戶名 outPuttext=outPuttext+tempStringArray[GetRandomNum(0,tempStringArray.length)] } return outPuttext; } console.log(GetRadomUserName(7,16)) 插入200萬數據 有了生成隨機數和隨機用戶名的方法,就可以生產百萬級數據了。此處代碼會在視頻中作詳細講解。代碼如下: var db = connect('company'); db.randomInfo.drop(); var tempInfo = []; for (let i=0;i<2000000;i++){ tempInfo.push({ username:GetRadomUserName(7,16), regeditTime:new Date(), randNum0:GetRandomNum(100000,999999), randNum1:GetRandomNum(100000,999999), randNum2:GetRandomNum(100000,999999), randNum3:GetRandomNum(100000,999999), randNum4:GetRandomNum(100000,999999), randNum5:GetRandomNum(100000,999999), randNum6:GetRandomNum(100000,999999), randNum7:GetRandomNum(100000,999999), randNum8:GetRandomNum(100000,999999), randNum8:GetRandomNum(100000,999999), }) } db.randomInfo.insert(tempInfo); 這個過程可能2-3分鐘,根據自己的電腦配置不同,會有差別。 插入完成后,我們可以使用 db.randomInfo.stats() 這個命令查看數據中的數據條數。 全部代碼: //生成隨機數 function GetRandomNum(min,max){ let range = max-min; //得到隨機數區間 let rand = Math.random(); //得到隨機值 return (min + Math.round(rand *range)); //最小值+隨機數取整 } //console.log(GetRandomNum(10000,99999)); //生成隨機用戶名 function GetRadomUserName(min,max){ let tempStringArray= "123456789qwertyuiopasdfghjklzxcvbnm".split("");//構造生成時的字母庫數組 let outPuttext = ""; //最后輸出的變量 //進行循環,隨機生產用戶名的長度,這里需要生成隨機數方法的配合 for(let i=1 ;i<GetRandomNum(min,max);i++){ //隨機抽取字母,拼裝成需要的用戶名 outPuttext=outPuttext+tempStringArray[GetRandomNum(0,tempStringArray.length)] } return outPuttext; } // console.log(GetRadomUserName(7,16)) // var startTime=(new Date()).getTime(); var db = connect('company'); db.randomInfo.drop(); var tempInfo = []; for (let i=0;i<2000000;i++){ tempInfo.push({ username:GetRadomUserName(7,16), regeditTime:new Date(), randNum0:GetRandomNum(100000,999999), randNum1:GetRandomNum(100000,999999), randNum2:GetRandomNum(100000,999999), randNum3:GetRandomNum(100000,999999), randNum4:GetRandomNum(100000,999999), randNum5:GetRandomNum(100000,999999), randNum6:GetRandomNum(100000,999999), randNum7:GetRandomNum(100000,999999), randNum8:GetRandomNum(100000,999999), randNum8:GetRandomNum(100000,999999), }) } db.randomInfo.insert(tempInfo); 總結:這節課主要是為講解MongoDB的索引作準備,我們用隨機數的方法構建了一個百萬級的數據表,如果你有興趣繼續往下學習聯系,這節課必須動手作一下。以后這篇文章的學習全是基于這個代碼。 ## 第16節:索引:索引入門 ## 集合中已經有了200萬條的數據,可以進行索引的操作了。我們先來建立一個索引,然后看看它的查詢性能到底提升了多少倍。這節課的內容不會很難,主要掌握索引的建立方法即可。 普通查詢性能 我們先制作一個普通查詢,隨便查找一個用戶名,并計算出查詢和打印的時間,因為有200萬條數據,所以性能不會很高。 var startTime = new Date().getTime() //得到程序運行的開始時間 var db = connect('company') //鏈接數據庫 var rs=db.randomInfo.find({username:"tfruhjy8k"}) //根據用戶名查找用戶 rs.forEach(rs=>{printjson(rs)}) //循環輸出 var runTime = new Date().getTime()-startTime; //得到程序運行時間 print('[SUCCESS]This run time is:'+runTime+'ms') //打印出運行時間 上邊的代碼就是一個普通的查詢,只不過是記錄了時間。在終端運行后,可以得到大概的運行時間是0.8秒左右(電腦性能不同,有所不同),第一次無緩存的運行時間大概是3.5秒左右。這個時間是沒辦法滿足我們的日常查詢的。 建立索引 試著為用戶名(username)建立索引。建立索引只需要一句話就可以了。 db.randomInfo.ensureIndex({username:1}) 查看現有索引 db.randomInfo.getIndexes() 終端的結果,現在只有一個索引值: [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "company.randomInfo" } ] 那現在使用命令建立一下索引db.randomInfo.ensureIndex({uername:1}),我的電腦大概要50秒左右,建立好后我們重新使用db.randomInfo.getIndexes(),查看一下結果。 結果如下:已經變成了兩條索引。 [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "company.randomInfo" }, { "v" : 2, "key" : { "username" : 1 }, "name" : "uername_1", "ns" : "company.randomInfo" } ] 然后我們在來load一下demo07.js文件(load(‘./demo07.js’)),看一下現在多少秒可以查詢出來。這時候查詢的時間縮短到了4ms左右,查詢性能提升了大概200倍左右。 總結:無論是在關系型數據庫還是文檔數據庫,建立索引都是非常重要的。前邊講了,索引這東西是要消耗硬盤和內存資源的,所以還是要根據程序需要進行建立了。MongoDB也給我們進行了限制,只允許我們建立64個索引值。 ## 第17節:索引:復合索引 ## 這節課先來看看什么樣的數據你使用索引會變慢,然后學習一下復合索引的使用和語法。通過這節課我們需要對所以使用的時機有所了解,避免畫蛇添足,產生不必的麻煩。 索引中的小坑 記得我剛學MongoDB時,學會了索引,我就到處想用,甚至幾百條數據的集合(collections),我也自作聰明的用一下,但結果往往是畫蛇添足,走了不少彎路。通過實際開發和性能對比,我自己總結了幾條不用索引的情況(不一定對,但是自己的經驗之談)。 數據不超萬條時,不需要使用索引。性能的提升并不明顯,而大大增加了內存和硬盤的消耗。 查詢數據超過表數據量30%時,不要使用索引字段查詢。實際證明會比不使用索引更慢,因為它大量檢索了索引表和我們原表。 數字索引,要比字符串索引快的多,在百萬級甚至千萬級數據量面前,使用數字索引是個明確的選擇。 把你經常查詢的數據做成一個內嵌數據(對象型的數據),然后集體進行索引。 復合索引 好了上邊我們講了一大堆理論,現在來看復合索引。復合索引就是兩條以上的索引。上節課我們已經把username字段建立了索引,我們現在把randNum0,這個字段也設置成索引。 db.randomInfo.ensureIndex({randNum0:1}) 建立好后,我們再用查詢索引狀態命令進行查詢。 db.randomInfo.getIndexes() 這時候已經是兩個自建索引了,一共有三個索引。 [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "company.randomInfo" }, { "v" : 2, "key" : { "username" : 1 }, "name" : "username_1", "ns" : "company.randomInfo" }, { "v" : 2, "key" : { "randNum0" : 1 }, "name" : "randNum0_1", "ns" : "company.randomInfo" } ] 兩個索引同時查詢 我們同時查詢兩個索引的值,看看效果是怎么樣的。 var startTime=new Date().getTime(); var db = connect('company'); var rs= db.randomInfo.find({username:'7xwb8y3',randNum0:565509}); rs.forEach(rs=>{printjson(rs)}); var runTime = new Date().getTime()-startTime; print('[Demo]this run time is '+runTime+'ms'); 從性能上看并沒有什么特殊的變化,查詢時間還是在4ms左右。MongoDB的復合查詢是按照我們的索引順序進行查詢的。就是我們用db.randomInfo.getIndexes()查詢出的數組。 指定索引查詢(hint) 課程開始時,我說了數字的索引要比字符串的索引快,這就需要一個方法來打破索引表的查詢順序,用我們自己指定的索引優先查詢,這個方法就是hint(). var rs= db.randomInfo.find({username:'7xwb8y3',randNum0:565509}).hint({randNum0:1}); 由于數據量和復雜成都還是不大,所以你看不出來明顯的性能提升,但是要相信技術胖,等工作中遇到大數據時,一定會得到很好的效果的。 刪除索引 當索引性能不佳或起不到作用時,我們需要刪除索引,刪除索引的命令是dropIndex(). db.randomInfo.dropIndex('randNum0_1');//索引的唯一ID 這里需要注意的是刪除時填寫的值,并不是我們的字段名稱(key),而是我們索引查詢表中的name值。這是一個小坑,希望小伙伴們不要踩中。 總結:這節主要內容還是操作索引,包括復合索引的建立,刪除。和一些使用索引的小竅門。 ## 第18節:索引:全文索引 ## 有些時候需要在大篇幅的文章中搜索關鍵詞,比如我寫的文章每篇都在萬字以上,這時候你想搜索關鍵字是非常不容易的,MongoDB為我們提供了全文索引。 準備工作: 這節我們先建立一個集合(collections)-info,然后插入一小段文章,作用就是為建立全文索引提供數據,當然我們不再建立百萬級數據,我們只是看一下效果。 db.info.insert({contextInfo:"I am a programmer, I love life, love family. Every day after work, I write a diary."}) db.info.insert({contextInfo:"I am a programmer, I love PlayGame, love drink. Every day after work, I playGame and drink."} 當然這很簡單,再次強調這只是文章需要,實際工作中這么簡單的數據沒必要建立全文索引。 建立全文索引 db.info.ensureIndex({contextInfo:'text'}) 需要注意的是這里使用text關鍵詞來代表全文索引,我們在這里就不建立數據模型了。 全文索引查找 建立好了全文索引就可以查找了,查找時需要兩個關鍵修飾符: $text:表示要在全文索引中查東西。 $search:后邊跟查找的內容。 db.info.find({$text:{$search:"programmer"}}) 查找多個詞 全文索引是支持多個次查找的,比如我們希望查找數據中有programmer,family,diary,drink的數據(這是或的關系),所以兩條數據都會出現。 db.info.find({$text:{$search:"programmer family diary drink"}}) 如果我們這時候希望不查找出來有drink這個單詞的記錄,我們可以使用“-”減號來取消。 dbd .info.find({$text:{$search:"programmer family diary -drink"}}) 轉義符: 全文搜索中是支持轉義符的,比如我們想搜索的是兩個詞(love PlayGame和drink),這時候需要使用\斜杠來轉意。 db.info.find({$text:{$search:"\"love PlayGame\" drink"}}) 總結:全文索引在工作還是經常使用的,比如博客文章的搜索,長文件的關鍵詞搜索,這些都需要使用全文索引來進行。這節課的知識并不難,還是那句話,你看是不可能學會的,一定要動手練習。當然索引還有很多知識,這里我們只講最常用的知識,把小伙伴引入門就好,也就是常說的用20%的精力,學會80%的知識,然后在工作中進行迭代磨練。雖然MongoDB的索引文章結束了,但是MongoDB的文章還沒有結束,下篇文章開始學習如何管理MongoDB。 ## 第19節:管理:用戶的創建、刪除與修改 ## 安裝好MongoDB時,它為我們默認開了一個最高管理權限方便我們管理數據庫,我們可以用mongo鏈接數據庫,就是這個原理。但在實際開發中并一般不能使用這個用戶,因為大家都知道和最高權限的原因,安全性和可靠性都不適合,所以要對MongoDB的用戶進行管理。這節課我們就學習一下MongoDB的用戶管理。 創建用戶: 首先要進入我們的admin庫中,進入方法是直接使用use admin 就可以。進入后可以使用show collections來查看數據庫中的集合。默認是只有一個集合的(system.version)。 創建用戶可以用db.createUser方法來完成,里邊參數還是蠻多的,代碼我寫在下邊,然后對每一項做出了解釋。 db.createUser({ user:"jspang", pwd:"123456", customData:{ name:'技術胖', email:'web0432@126.com', age:18, }, roles:['read'] }) 當然我們還可以單獨配置一個數據庫的權限,比如我們現在要配置compay數據庫的權限為讀寫: db.createUser({ user:"jspang", pwd:"123456", customData:{ name:'技術胖', email:'web0432@126.com', age:18, }, roles:[ { role:"readWrite", db:"company" }, 'read' ] }) 內置角色: 數據庫用戶角色:read、readWrite; 數據庫管理角色:dbAdmin、dbOwner、userAdmin; 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManage; 備份恢復角色:backup、restore; 所有數據庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase 超級用戶角色:root 內部角色:__system 查找用戶信息 我們直接可以使用查找的方法,查找用戶信息。命令很簡單: dbd .system.users.find() 刪除用戶: 刪除名利也是非常簡單,直接用remove就可以刪除這個用戶的信息和權限。 db.system.users.remove({user:"jspang"}) 建權: 有時候我們要驗證用戶的用戶名密碼是否正確,就需要用到MongoDB提供的健全操作。也算是一種登錄操作,不過MongoDB把這叫做建權。 db.auth("jspang","123456") 如果正確返回1,如果錯誤返回0。(Error:Authentication failed。) 啟動建權 重啟MongoDB服務器,然后設置必須使用建權登錄。 mongod --auth 啟動后,用戶登錄只能用用戶名和密碼進行登錄,原來的mongo形式鏈接已經不起作用了。相應的用戶權限也對應妥當。實際項目中我們啟動服務器必須使用建權形式。 登錄 如果在配置用戶之后,用戶想登錄,可以使用mongo的形式,不過需要配置用戶名密碼: mongom -u jspang -p 123456 127.0.0.1:27017/admin 這時候我們就可以用給我們的權限對數據庫操作了。 ## 第20節:管理:備份和還原 ## 作為一個數據庫管理員,對數據庫的備份和還原是比作的兩項工作。其實用起來是相當簡單的,就是mongodump和mongorestore兩個命令。 數據備份 先來看一下mongodump備份的基本格式,其實這就是條在終端中執行的命令。 mongodump --host 127.0.0.1 --port 27017 --out D:/databack/backup --collection myCollections --db test --username username --password password 比如現在我們備份所有MongoDB里的庫到D盤的databack文件夾下,就可以把命令寫成這樣 mongodump --host 127.0.0.1 --port 27017 --out D:/databack/ 數據恢復 備份好后,如果數據庫有意外或者遭受到了攻擊,我們要進行回復數據庫,這時候就可以使用mongorestore命令。 還是先看一下它的基本格式 mongorestore --host 127.0.0.1 --port 27017 --username username --password password <path to the backup> 比如我們現在不小心刪除了一個collections的數據,要進行恢復。現在刪除randomInfo集合。 db.randomInfo.drop() 使用命令進行恢復 mongorestore --host 127.0.0.1 --port 27017 D:/databack/ 總結:兩個命令很簡單,甚至你可以寫成腳本和定時任務,讓他每天自己執行。但是如果你真的使用了MongoDB數據庫,這是一個最基本的操作,還是要會使用的。 ## 第21節:管理:圖形界面管理(完結) ## 這節課我們主要看看圖形界面,圖形界面相對比較簡單,特別是我們已經會了很多終端的操作方法,所以我就不寫文章了,大家直接看視頻吧。 本文鏈接:http://jspang.com/post/mongodb.html
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看