1. 程式人生 > >MongoDB常用命令帥哥特供版

MongoDB常用命令帥哥特供版

MongoDB常用命令帥哥特供版

  • 沒錯這裡說的帥哥就是我自己

MongoDB常用命令

常用命令

命令 參考釋義
help 顯示基本操作命令
db.help() 顯示資料庫操作命令
db.collection.help() 顯示集合操作命令
sh.help() 顯示資料庫分片操作命令
rs.help() 顯示副本集操作命令
help admin 顯示管理員操作命令
help connect 顯示連線資料庫命令
help keys 顯示快捷鍵
help misc 顯示其他該知道的東西
show dbs 顯示所有資料庫列表
show collections 顯示當前資料庫所有集合列表
show users 顯示所有使用者列表
show logs 顯示所有日誌名稱列表(預設為global)
use dbname 切換/建立資料庫(若不存在則自動建立)

資料庫相關

命令 參考釋義
db.cloneCollection() 在MongoDB例項之間複製集合資料
db.cloneDatabase() 從指定主機上克隆資料庫到當前資料庫
db.commandHelp() 返回資料庫命令的幫助資訊
db.copyDatabase() 從指定的主機上覆制指定資料庫資料到某個資料庫
db.createCollection() 建立一個新的集合
db.currentOp() 顯示當前正在進行的操作。
db.dropDatabase() 刪除當前資料庫。
db.fsyncLock() 重新整理寫入磁碟並鎖定該資料庫,以防止寫入操作,並協助備份操作。
db.fsyncUnlock() 允許繼續進行寫入鎖住的資料庫(解鎖)
db.getCollection() 返回一個集合物件。需要傳遞一個在資料庫中存在的一個有效的集合名稱
db.getCollectionInfos() 返回當前資料庫中的所有集合資訊。
db.getCollectionNames() 列出當前資料庫中的所有集合。
db.getLastError() 檢查並返回最後一個操作的狀態。
db.getLastErrorObj() 返回上次操作狀態的檔案。
db.getLogComponents() 返回日誌訊息詳細級別。
db.getMongo() 返回MongoDB當前連線的連線物件。
db.getName() 返回當前資料庫的名稱。(也可以直接使用db;命令)
db.getPrevError() 返回包含自上次錯誤復位所有的錯誤狀態檔案。
db.hostInfo() 返回當前資料庫主機系統的相關資訊
db.killOp() 終止指定的操作。
db.listCommands() 顯示公共資料庫的命令列表。
db.logout() 登出登入
db.repairDatabase() 修復當前資料庫
db.resetError() 重置db.getPrevError()和getPrevError返回的錯誤資訊。
db.runCommand() 執行一個數據庫命令。
db.serverStatus() 返回當前資料庫狀態的概要
db.setLogLevel() 設定一個單獨的日誌資訊級別。
db.setProfilingLevel() 修改當前資料庫的分析級別。
db.shutdownServer() 關閉當前資料庫執行例項或安全停止有關操作程序
db.stats() 返回在當前資料庫的狀態報告。
db.version() 返回當前資料庫的版本資訊

集合相關

命令 參考釋義
db.collection.bulkWrite() 批量寫入
db.collection.count() 返回集合總數或匹配查詢的結果集總數
db.collection.copyTo() 已過時。現此操作被封裝在兩個資料庫例項之間的複製資料中
db.collection.createIndex() 建立一個集合索引
db.collection.dataSize() 返回集合的大小
db.collection.deleteOne() 刪除集合中的一個文件
db.collection.deleteMany() 刪除集合中的多個文件。
db.collection.distinct() 返回具有指定欄位不同值的文件(去除指定欄位的重複資料)
db.collection.drop() 刪除當前資料庫中的collection集合
db.collection.dropIndex() 刪除一個集合中的指定索引
db.collection.dropIndexes() 刪除一個集合中的所有索引
db.collection.ensureIndex() 已過時。現使用db.collection.createIndex() 。
db.collection.explain() 返回各種方法的查詢執行資訊
db.collection.find() 查詢集合,無引數則查詢所有,並返回一個遊標物件。
db.collection.findAndModify() 查詢並修改
db.collection.findOne() 查詢單條資料
db.collection.findOneAndDelete() 查詢單條資料並刪除
db.collection.findOneAndReplace() 查詢單條資料並替換
db.collection.findOneAndUpdate() 查詢單條資料並更新
db.collection.getIndexes() 返回當前集合的所有索引陣列
db.collection.group() 提供簡單的資料聚合功能
db.collection.insert() 在當前集合插入一條或多條資料(或叫文件)
db.collection.insertOne() 在當前集合插入一條資料
db.collection.insertMany() 在當前集合插入多條資料
db.collection.isCapped() 判斷集合是否為定容量
db.collection.reIndex() 重建當前集合的所有索引
db.collection.replaceOne() 替換集合中的一個文件(一條資料)
db.collection.remove() 從當前集合刪除資料
db.collection.renameCollection() 重新命名集合名稱
db.collection.save() 在當前集合插入一條資料,同insert()方法的區別:當要插入的資料已存在時,save會執行更新操作,而insert方法會忽略當前操作
db.collection.stats() 返回當前集合的狀態
db.collection.storageSize() 返回當前集合已使用的空間大小
db.collection.totalSize() 返回當前集合的總佔用空間,包括所有檔案和所有索引
db.collection.totalIndexSize() 返回當前集合所有的索引所佔用的空間大小
db.collection.update() 修改集合中的資料。
db.collection.updateOne() 修改集合中的一條資料。
db.collection.updateMany() 修改集合中的多條資料。
db.collection.validate() 執行對集合驗證操作。

Mongodb初始化操作

註解

預設: mongo的資料庫和集合的建立是隱式建立, 當進行建立集合中的欄位時,自定建立該資料庫,如: db.c1.insert({});即同時建立了c1的集合

手動: 顯式建立集合db.createCollection('c1');建立c1集合

安裝

Mac 下直接使用brew
Ubuntu 直接使用apt-get install mongodb
MongoDB預設使用27017埠

關閉伺服器

關閉伺服器:
    mongod  --shutdown  --dbpath /database/mongodb/data/
    mongod 命令的 shutdown 選項能幹淨的關閉 MongoDB 服務。

啟動

Mac下:
  如果找不到命令直接進入:
        /usr/local/Cellar/mongodb/3.4.4/bin
    
1.啟動服務(MacOS&linux除路徑外都一樣)
    ./mongod --dbpath=/usr/local/Cellar/mongodb/3.4.4/data(指定的資料庫儲存位置) --logpath=/usr/local/Cellar/mongodb/3.4.4/log/log(指定的日誌儲存位置,這裡必須指定到檔案而不是目錄,否則會報錯) --fork(後臺執行)
    
我在Mac中使用的啟動服務的方式
/usr/local/Cellar/mongodb/3.4.4/bin/mongod --dbpath=/usr/local/Cellar/mongodb/3.4.4/data --logpath=/usr/local/Cellar/mongodb/3.4.4/log/log
    
    啟動注意:
        mongodb目錄下的data和log目錄我在20170509安裝時db.version()3.4.4 MacOX系統時,目錄下沒有這個目錄.需要自行建立.
    
2.連線資料庫(命令列操作)
    ./mongo
    
3.關閉資料庫
    可以使用Killall或pkill 決不能用Kill -9
    或者:
    如果處理連線狀態,那麼直接可以通過在 admin 庫中傳送 db.shutdownServer()指令去停止 MongoDB 例項;
    
4.mongod啟動命令常用引數
    --dbpath 指定資料庫目錄
    --port  指定資料庫的埠,預設27017
    --bind_ip   繫結IP
    --directoryperdb為每個db建立一個獨立子目錄
    --logpath   自定日誌存放目錄
    --logappend對存在的日誌追加,如果沒有這個選項,新日誌將會覆蓋舊的日誌
    --pidfilepath指定程序檔案路徑,如果不指定,將不產生程序檔案
    --keyFile叢集模式的關鍵標識
    --journal 啟用日誌
    --nssize 指定.ns檔案的大小, 單位mb預設是16M,最大2GB
    --maxConns 最大的併發連線數
    --notablescan不允許進行表掃描
    --noprealloc關閉資料檔案的預分配功能
    --fork以後臺Daemon形式執行服務
    --config 指定配置檔案
    --smallfiles 使用較小的預設檔案大小
    --repair 通過丟棄無效或損壞的資料重新構建資料庫和索引,這些資料可能由於意外的系統重新啟動或崩潰而出現。
    比如非法關閉的時候第二次啟動報lock檔案錯, rm /安裝目錄/mongodb/mongo.lock && ./mongod  --repair
    跟多引數利用Mongod --help進行檢視

邏輯結構

MysqlMongodb
database(庫)database(庫)
table(表)collection(集合)
row(行)document(文件)
column(列)field(域)
index(索引)index(索引)
table joins(連表)
primary key(主鍵)primary key(主鍵)

mongodb常用資料型別

1.null 
    Null型別用來標識空值或不存在的欄位
    如:{'one':null}

2.bool
    布林型有兩種值true和false
    如:{'one':true}

3.32位整數
    mongoDB的控制檯使用js引擎進行輸入,而js僅支援64位浮點數,所以32位整數會被轉義.

4.64位整數
    64位整數和32位整數一樣,在MongoDB控制檯使用時會被轉義為64位浮點數.
    
5.64位浮點數
    MongoDB控制檯數字的預設型別
    如:{"one":2.02}{'one':10}
    
6.字串
    utf字串都可以表示為字串型別的資料
    如:{"one":"Hello World"}

7.符號
    在MongoDB控制檯中不支援這種型別,將自動轉義為字串
    
8.ObjectId型別
    物件ID是文件中唯一的12位的ID
    0|1|2|3|4|5|6|7|8|9|10|11
    時間戳 |機器 |PID |計數器
    如: ObjectId("59115566f4d5125386de535e")
    
9.日期
    注意: 使用的時候加上 new
    如: {"one":new Data()}
    
10.正則表示式
    文件鍵值可以包含正則表示式, 其正則表示式採用js語法來表示
    如: {"one":/ho/i}
    
11.程式碼
    文件中可以包含js程式碼
    如: {"one":function(){/*....../*}}
    
12.陣列
    文件中鍵值可以標識為陣列, 在陣列內還可以巢狀陣列
    如: {"x":["a","b",["c","d"]]}
    
13,內嵌文件
    文件可以包含別的文件,可以作為值嵌入到父文件中
    如: {"x"{"name":"Tom","age":20}}


常用命令(控制檯中常用的操作命令)

db.version();                       檢視版本號
show dbs;                           檢視所有庫(同時顯示庫大小)
show databases;                     檢視所有庫
db.getCollectionInfos({欄位名: /正則/}) 返回具有當前資料庫的集合資訊(即集合名稱和選項)的文件陣列。
db.getCollectionNames()            返回一個數組,該陣列包含當前資料庫中所有集合的名稱。
如果要過濾可以使用:
結尾不是usdt不顯示,這個其實就是JS的函式
db.getCollectionNames().filter(function(el) {return el.indexOf('usdt') !== -1})

db.copyDatabase('oldName','newName')複製庫
db;                                 檢視當前所在庫
use 庫名;                           選擇庫
show collections;                   檢視所有集合
db.shutdownServer();
關閉伺服器(需要先行 use 到 admin)

db.c1.stats();                      檢視集合狀態
db.c1.insert(json格式);             插入資料(此處db代表當前庫)(c1為集合)
db.c1.find([where]);                查詢時資料[條件](c1為集合)
db.c1.update({where},{update});     修改資料

db.c1.drop();                       刪除集合及其文件
db.c1.remove({});                   刪除集合中的文件,
db.dropDatabase();                  刪除當前庫

固定集合
db.c1.isCapped();                   判斷是否是固定集合
db.c1.stats();                      檢視集合狀態

使用者操作:
db.system.users.find();             檢視使用者列表
show users;                         檢視所有使用者


更多命令使用可以在mongo中使用help檢視;
想知道當前資料庫支援那些方法: db.help();
想知道當前集合支援那些方法: db.user.help();user為合集名;

索引

system.indexs
    該庫裡面的集合中的所有_id(主鍵索引)所有都放在這裡面.

mongodb增刪改查的高階應用(Capped固定集合&GridFs大檔案管理)

固定集合Capped Collection

  • 固定集合介紹

capped collections是效能出色的有著固定大小的集合,以LRU(Least Recently Used最近最少使用)規則和插入順序進行age-out(老化移除)處理,自動維護集合中物件的插入順序,在建立時要預先指定大小,如果空間用完,新新增的物件將會取代集合中最老的物件.永遠保持最新資料.

功能特點:
普通集合:
	隨著內容的增多,空間自動增大.

固定集合:
可以插入及更新,但更新不能超出collection的大小,否則更新失敗.不允許刪除,但是可以呼叫drop()撒謊拿出集合中的所有行,但是drop後需要顯式的重建集合,在32位機上,一個capped collection的最大值約為482.5m,64位機上只受系統檔案大小的限制.

屬性及用法:
屬性1.固定集合插入速度極快.
屬性2.插入順序的查詢輸出極快.
屬性3.能夠在插入最新資料時,淘汰最早的資料.

用法1: 儲存日誌資訊.
用法2: 快取一些少量文件.
  • 建立固定集合
不像普通集合,固定集合需要顯式的建立使用.
使用createCollection命令來建立.

db.createCollection('c1',{capped:true,size:10000,max:5});
建立一個固定集合,名為c1,大小10000,最大5個文件

注意:
	指定文件上限,必須指定大小.文件限制是在容量沒有滿時進行淘汰,如果滿了,就要根據容量限制來進行淘汰
	
db.createCollection('集合名',capped:bool,size:num,max:num);
集合名: 建立集合的名稱
capped: 建立一個固定集合
size:   最大檔案多少
max:    最大文件個數
注意: 指定文件上線,必須指定大小.文件限制是在容量沒滿時進行淘汰.
要是滿了,就根據容量限制來進行淘汰.

  • 轉換普通集合為固定集合convertTocapped
轉換為普通集合:
把普通集合轉換為固定集合需要使用db.runCommand({convertTocapped:'c1',size:10000,max:5});
把c1普通集合轉換為固定集合,大小為10000,

自然排序:
固定集合文件安排插入順序儲存的, 預設情況下查詢就是按照插入順序返回的.也可以使用$natural調整返回順序.
db.c1.find().sort({'$natural':1});
1表示預設順序,-1則相反.
判斷使用: db.c1.isCapped();
狀態使用: db.c1.stats();


db.runCommand({convertToCapped:'集合名',size:num,max:num});
集合名: 要轉換為固定集合的普通集合名
size: 檔案大小
max: 文件上限

GridFs大檔案

  • GridFs講解
GridFs是一種儲存在MongoDB中的大的二進位制檔案的機制,使用GridFs的原因有:
1.儲存巨大檔案,如:視訊,高清圖片等,利用GridFs可以簡化需求.
2.GridFs會直接利用已建立的複製和分片機制,故障回覆和擴充套件都很容易.
3.GridFs可以避免使用者上傳內容的檔案系統出現問題.
4.GridFs不產生磁碟碎片.

GridFS 用於儲存和恢復那些超過16M(BSON檔案限制)的檔案(如:圖片、音訊、視訊等)。
GridFS 也是檔案儲存的一種方式,但是它是儲存在MonoDB的集合中。
GridFS 可以更好的儲存大於16M的檔案。
GridFS 會將大檔案物件分割成多個小的chunk(檔案片段),一般為256k/個,每個chunk將作為MongoDB的一個文件(document)被儲存在chunks集合中。
GridFS 用兩個集合來儲存一個檔案:fs.files與fs.chunks。
每個檔案的實際內容被存在chunks(二進位制資料)中,和檔案有關的meta資料(filename,content_type,還有使用者自定義的屬性)將會被存在files集合中。
  • GridFs應用
GridFs使用兩個表來儲存資料:
files:  包含資料物件(儲存基本屬性:檔名稱,上傳時間,等)
chunks: 包含其他一些相關資訊的二進位制塊(儲存資料的真正檔案內容).
為了使多個GridFs命名為一個單一的資料庫,檔案和塊都有一個字首,預設情況下,字首是fs,所以任何預設的GridFs儲存將包括名稱空間fs.files和fs.chunks.
各種第三方語言可以更改其字首.

新增檔案
mongofiles put 檔名

下載檔案
mongofiles get 檔名

查詢檔名
mongofiles list 檔名

引數說明
-d 指定資料庫,預設死 fs mongofiles list –d testGridfs

-u -p 指定使用者名稱,密碼

-h 指定主機

-port 指定主機埠

- -c 指定集合名,預設為 fs

-t 指定檔案的 mime型別,預設會忽略.

索引&效能優化

  • 建立索引(普通索引)
建立索引的函式: ensureIndex()
例子:在 Name 上 建立索引 1(升序)-1(降序)

db.c1.ensureIndex({name:1});

當系統已經有大量資料時,建立索引會非常耗時,需要在後臺執行.只需指定background:true即可

db.c1.ensureIndex({age:1},{background:true});

  • 唯一索引
只需要在 ensureIndex 命令中指定unique:true指定索引型別即可.
注意:
	如果集合中該欄位,含有同樣的兩條資料,建立唯一索引將失敗.
	
例如:
	db.c1.ensureIndex({name:1},{unique:true});
	建立 c1集合中 name 欄位為唯一索引.
  • 檢視索引
db.collection.getIndexKeys();
檢視集合中的所有索引
例子:
db.c1.getIndexKeys();
檢視 c1集合中的所有索引
  • 刪除索引
dropIndexes();
刪除所有索引
dropIndex({});
刪除指定索引

主:
	_id 索引不能被刪除

例子:
	db.c1.dropIndexes();
	刪除c1集合中的所有索引
	
	db.c1.dropIndex({name:1});
	刪除c1集合中name 欄位的索引

效能優化

  • explain 執行計劃
mongo提供了 一個 explain 命令讓我們獲知系統如何處理查詢請求,利用 explain 命令我們可以很好的觀察系統如何使用索引來加快搜索,同時有針對性的進行優化

db.c3.find({age:$gt:10},{name:1}).explain();

{
	'cursor':'BtreeCursor age_1', # 返回遊標型別(BasicCuror 或 BtreeCursor)
	'nscanned': 0,	# 被掃描的文件數量
	'nscannedObjects':0,	
	'n':0,	# 返回的文件數量
	'millis':0,	# 耗時毫秒()
	'indexBounds':{	# 所使用的索引
					'age':[
						[
							45,
							1.7.97123123e+308
						]
					]
	}
}

MongoDB集合(collection)操作

註釋:

當查詢時同時使用sort,skip,limit,無論位置先後 最後執行順序 sort再skip再limit。要不然擷取的資料會亂.由結果可以得出,當sort,skip,limit一起使用時,無論其位置變化,總是先sort再skip,最後limit。


mongo中可以使用js語法:
    如: 
        insert測試資料時,一條一條的覺得很慢,可以使用js的for迴圈.
        for(i=0;i<10;i++){
        	db.c1.insert({name:'nihao'+i,sex:i});
        }
        
    如:
        findOne將查詢的結果進行賦值再新增資料(find不能用,即使只find了一條也不能用)
        var x = db.c3.findOne({x:x});
        x.test1 = '測試1'
        x.test2 = '測試2'
        x(輸出x得到之後複製的內容)
  • 增加(insert)
db.collection.insert({document});
db.collection.save({document});
    1.document: 為json格式的資料, 可以使用多層巢狀, 及其json中巢狀陣列([]);
   
兩者不同在於:
        insert插入時,主鍵相同報錯,不同則插入.save插入時,主鍵相同修改資料, 不同則插入.
        
例子:
    查詢出的結果:
    { "_id" : ObjectId("59128ebc330f067165b51d8f"), "name" : "liuhao" }
    { "_id" : '1', "name" : "zhangsan" }
    { "_id" : 1, "name" : "zhangsan" }
    在此處需要注意的是: 
        主鍵_ID是可以手動指定的.
        插入_id主鍵ID時,{_id:'1'}和{_id:1}是不一樣的,但是{_id:'1'}等於{_id:"1"}
  • 儲存(save)
集合的欄位存在即修改不存在則刪除

利用save和findOne({});利用save的_id存在則更新,不存在則插入的機制以及findOne({})查詢的結果可以直接賦值成一個變數進行操作(變數內的值可以進行新增刪除).可以實現非常厲害的功能.
即將查詢出的一條資料進行修改,再寫入集合.

如例:
var x = db.c3.findOne({name:'liuhao'});

x.sex = 1
x.age = 18
x.addr = '河南'
x.realName = '劉'
x.hobby = '波多野'

db.c3.save(x);
將name=liuhao的欄位查詢出同時賦值給一個變數.
通過變數的下標直接進行操作,添加個人資訊.
利用save的存在即修改,來進行修改儲存資料操作.

  • 刪除(remove)
db.collection.remove({query},{justOne});   
刪除該集合中的資料:
    query :(可選)刪除的文件的條件。
    justOne : (可選)如果設為 true 或 1,則只刪除一個文件
注意 如果不寫條件, 則刪除整個集合中的所有資料

db.collection.drop();
刪除該集合

db.dropDatabase();
刪除當前資料庫,預設為 test,可以使用 db 命令檢視當前資料庫名。

  • 查詢(find)
find批量查詢
findOne查詢一個(自帶 遊標)
db.collection.find({query},{projection}).pretty;     
如果不寫條件則查詢所有 相當於 MySql:select * 
    1.query: json格式的where條件
    2.projection: 可選的,從查詢結果保留什麼
    3.如果想以易讀的方式展示使用.pretty()


例如:
    db.c1.find({sex:0},{name:0});
    查詢sex=0的name欄位不顯示
   db.c2.find({'post.title':'a1','post.title':'b1'});
    查詢json中巢狀陣列,以陣列內部值作為條件查詢(post下陣列中title=a1且title=b2).{ "_id" : ObjectId("5916a0ff0ca8e2abdb4689a6"), "name" : "user2", "post" : [ { "title" : "a1" }, { "title" : "b1" }, { "title" : "c1" } ] }


  • 修改(update)
db.collection.update();
  • 表示式
> 大於 - $gt
< 小於 - $lt
>= 大於等於 - $gte
<=  小於等於 - $lte
!=  不等於  -  $ne

查詢中使用表示式:
    查詢的條件一般在json內測
    如: sex > 0
        db.c1.find({sex:{$gt:0}});
        
    合在一起: 0 < sex < 10
    db.c1.find({sex:{$gt:0,$lt:10}});
        
    修改中使用表示式:
        修改的條件一般在json外側


$or  或者:
    db.collection.find($or:[{age:1},{age:2}]); # 查詢結果為age=1或者age=2的資料
    如:
        db.c1.find({$or:[{age:1},{age:2}]});
        
and 並且:
    db.collection.find({ke1:value1,key2:key2});
    mongo中並無,and操作符號,一般在查詢時,以json格式寫入的key,即為並且操作.需要注意的是: key1,key2應該是同一個欄位的條件. 如果是兩個欄位則以第二個Key為準.
    如:
        db.c1.find({age:1,name:'liu1'}); # 正確寫法,查詢age=1且name='liu1'的欄位
        db.c1.find({age:1,age:2}); # 錯誤的寫法, 結果將age=2為標準作為查詢

$in:[array] 在該陣列中的
    db.collection.find({age:{$in:[1,2,3]}});
    查詢age欄位,其值在[1,2,3]中的結果
     $in和$all類似,但是in只要命中其中一個即可.
    如:
        db.c1.find({age:{$in:[1,2,3,4,5]}}); 
        查詢age欄位,其值在[1,2,3,4,5]中的結果
        
$nin:[array] 不在該陣列中
    db.collection.find({age:{$nin:[1,2,3]}});
    不包含在[1,2,3]中的欄位
    
    如:
        db.c1.find({age:{$nin:[1,2,3]}});
        查詢,不包含在[1,2,3]該陣列中的欄位.

$mod:[array] 取模運算(數學上叫做取餘)
    db.collection({age:{$mod:[2,0]}});
    匹配查詢和2餘0的欄位.
    
$all:[array] 匹配陣列中所有的值
    db.collection.find({age:{$all:[1,2,3]}});
    $all和$in類似,但是all需要匹配條件內所有的值
    
    如:
        db.c1.find({age:{$all:[1,2,3]}});
        匹配age欄位同時該欄位中,同時該欄位必須含有這三個值.

$size 匹配陣列長度
        db.collection.find({age:{$size:num}});
        值匹配陣列長度為num的欄位
        db.c1.find({age:{$size:3}});
        只匹配陣列長度為3的欄位

$exists:query 判斷一個元素是否存在
        db.things.find({age:{$exists:true}}); 
        查詢含有age的所有欄位
        db.things.find({age:{$exists:false}}); 
        查詢不存在age的所有欄位

$not:query 取反
    db.collection.find({欄位:{$not:{條件}}}});
    如:
        db.c1.find({age:{$not:{$mod:[2,0]}}});
        不匹配取餘結果,和2取餘為0的欄位.
        db.c1.find({name:{$not:/liu*/}});
        不匹配正則匹配的內容

正則表示式
        db.collection.find({name:/string/});
        如:
            db.c1.find({name:/liu/});
            使用正則匹配姓劉的

  • 高階查詢
count() 計算結果中的個數
        db.c1.count();  計算集合中文件的個數
        db.c1.find().count();   計算查詢結果中文件的個數
        下面這個效率低,耗記憶體.

        
        
limit() 讀取指定數量的資料記錄
    db.collection.find().limit(10);從0開始讀取10個
    但是該方法只有一個引數,不可以像MySQL中做分頁時那樣使用.
    要想自定義指定從N1獲取到N2資料,需要skip()方法的輔助.
    如:
        db.c1.find().skip(10).limit(10); #跳過前十個,從第十個開始向後取十個
    
skip()  跳過指定數量的資料
    db.collection.find().skip(number).limit(number);
    如:
        db.c1.find().skip(0).limit(10); # 從第0個開始向後取10個
        db.c1.find().skip(10).limit(10); # 從第10個開始向後取10個
        
sort()  將查詢結果進行排序
    db.collection.find().sort({key:1});
        key:1   升序
        key:-1  降序
    如:
        db.c1.find().sort({age:1}); # 升序排列
        db.c1.find().sort({age:-1}); # 降序排列
        
$elemMatch 匹配查詢
    db.collection.find({x:{$elemMatch:{a:1}}});
    匹配json物件(x)中陣列內json下標a為1的
    例如:
          db.c2.find({x:{$elemMatch:{a:1,b:{$gt:1}}}});
          查詢c2集合中json物件x下陣列內json物件的下標為a=1的且b>1的欄位
          db.c2.find({post:{$elemMatch:{title:'a1',title:'b1'}}});
          結果:
            { "_id" : ObjectId("5916a0ff0ca8e2abdb4689a6"), "name" : "user2", "post" : [ { "title" : "a1" }, { "title" : "b1" }, { "title" : "c1" } ] }
    
Null查詢
    Null: 值為Null, 欄位不存在.
    db.collection.find({x:null});
    查詢該值為Null的欄位
    
    如果本意是想查詢該欄位的某個值為Null型別時,其他欄位中不存在該值的也會認為是Null.所以在使用中為區分開, 我們需要做判斷.
    
    db.c3.find({sex:{$exists:1,$in:[null]}});
    查詢sex欄位存在,同時其值確實親為Null.
    或者使用$type
    db.c3.find({$type:10},name:'liu');
    查詢資料型別為10(Null),同時名稱為liu的資料.
  
$selice 剪取
     db.collection.find({},{x:{$slice:[a,b]}});
    從查詢結果中剪下資料,從a-b(從0開始可以只寫第二個值,可以為負數)
    
    db.c2.find({post:{title:1}},{post:{$slice:[0,4]}});
    查詢,post下的陣列下標為title的值為1的欄位,並剪下post下的陣列, 從0-4
    
    db.c2.find({},{post:{$slice:1}});
    查詢所有資料, 將post欄位下的陣列剪下0-1
    
  • 聚合操作
distinct() 取唯一值,鍵值去重
    db.collection.distinct('name')
    
    db.c1.distinct('name');
    檢視c1集合中name列的所有唯一的欄位



  • 遊標 cursors及cursor Methods
一般資料庫要麼一次性把資料都讀出來, 要麼以遊標的形式,連線資料庫一行一行的根據需求拿取資料,斷開資料.
為了避免,一次性把符合需求的資料全部拿出來, 有用遊標是一個不錯的方法.

var x = db.collection.find({});
將查詢結果複製在x中.不會直接輸出

x.hasNext();
判斷x中是否有下一個值true為有,false為空

x.next();
輸出一行查詢出的內容,查詢到無結果時會報錯.

高階更改操作

  • update 高階
    db.collection.update( criteria, objNew, upsert, multi )
    
引數說明:
Criteria:用於設定查詢條件的物件
Objnew:用於設定更新內容的物件
Upsert:如果記錄已經存在,更新它,否則新增一個記錄(預設0)需要指定魔術變數(如:$set,$inc)才能用
Multi:如果有多個符合條件的記錄,全部更新(預設0)
注意:預設情況下,只會更新第一個符合條件的記錄,如果直接修改的話, 會變成一個新的物件.之前的內容被替換為修改的內容, 之前的內容不存在.
如:
   b.c1.update({name:'liu0'},{age:111});
   原來的欄位變成age:111,其他內容消失.
   
如果想只修改一個欄位中的一個值,需要使用魔術變數$set
如:
    db.c3.update({name:'liu4'},{$set:{age:'10'}});
    
  • $inc 遞增
db.collection.update({x:x},{$inc:{x:x}},0,1);
可使用減號,匹配某欄位中的某個值自增多少(必須為整型).(update第四個值為true,修改符合要求所有欄位)
如果該欄位沒有, 則新增欄位,賦值然後自增.null值不可自增.

> db.c3.update({name:/liu/},{$inc:{age:10}},0,1);
正則匹配liu的欄位中age欄位全部加10

$set和$inc的區別:

都可以新增欄位,$set可以直接改掉.但是$inc在原來的值上可以加減(必須為整型.)
  • $unset 刪除指定欄位的field
db.collection.update({x:x},{$unset:{x:x}});
刪除x匹配欄位中的x的field(不能刪除_id)

db.c3.update({name:'liu'},{$unset:{sex:10}});
刪除欄位name=liu中sex為10的field

db.c3.update({},{$unset:{sex:21}},0,1);
刪除該合集中,所有sex=21欄位中的sex域

  • $push&$pushAll 在陣列的最後新增一個欄位
$push推入一個值
$pushALl推入一個數組
可推入重複值


  • $addToSet 也是在陣列的最後推入一個值
不可推入重複值


如果要一次性推入多個值需要和$each配合使用


  • $pop刪除陣列中的最後一個元素
db.collection.update({x,x},{$pop:{x:bool}});
bool為1時刪除最後一個
bool為-1時刪除第一個
  • $pull&$pullAll 如果陣列中的值存在則刪除,不存在則報錯
$pull 匹配一個值
$pullAll匹配一個數組
db.collection.update({x:x},{$pull:{x:1}});
刪除符合該條件的欄位中的x陣列中的該值(如果該值存在則刪除,不存在則報錯).




  • $rename重新命名該欄位

  • 特殊操作符 $
$操作符代表查詢記錄中第一個匹配條件的記錄項。



MongoDB資料庫管理

  • 注意
據稱讀寫分離, 主伺服器重啟之後,子伺服器會重新從主伺服器讀取資料,同時清空本伺服器資料.
所以要做好備份.
v3.4.4親測
測試使用停掉子伺服器,刪除主伺服器內容重寫其他內容.結果,資料庫連線後,子伺服器內容,同步.

資料匯出&資料匯入&資料備份&資料回覆

  • 資料匯入匯出
資料匯出:
    mongoexport
    命令列用於資料的匯出,預設匯出的檔案格式為JSON格式。當然也可以指定特定的檔案格式。
    
    ./mongoexport --help 檢視幫助
    
    引數:
        -h:資料庫宿主機的IP
        -u:資料庫使用者名稱
        -p:資料庫密碼
        -d:資料庫名字
        -c:集合的名字
        -f:匯出的列名
        -q:匯出資料的過濾條件
        --csv:匯出格式為csv(version v3.4.4需要使用--type=csv 同時,在-f 中指定匯出的欄位)
    注意:
        csv 格式,不匯出UID.
        
    具體操作:
        ./mongoexport -d test -c c1 -o c1.dat
        匯出該 c1集合中所有的資料,預設為 json 格式.
        ./mongoexport -d test -c c1 --type=csv -f name,age -o c1.dat
        匯出 c1集合中 name以及age 欄位的資料,格式為 csv 格式.
        
    
資料匯入:
    mongoexport
    
    具體操作:
        mongoimport -d test -c c1 c1.bat
        將 c1.bat 檔案匯入到 test 資料庫下的 c1集合中
        
    注意:
        json 格式匯入時,會自動隱式建立資料結構.
        
資料備份:
    mongodump
    
    具體操作:
        ./mongodump -d test -o ./testDb
    備份整個 test 資料庫到 當前目錄下 testDb 檔案.(不實用-o 指定路徑,預設到 bin 下的 dump 目錄下,使用 port 指定埠號 mongodump --port=27020)
    
資料恢復:
    mongorestore
    
    具體操作:
         sudo mongorestore -d test ./testDb/*
         匯入 當前目錄./testDb 下的所有資料到 test 資料庫中.
    
    注意:
        恢復資料需要使用root 使用者
        使用-drop 引數可以匯入的同時,刪除之前的內容.
        如下:
            sudo mongorestore -d test -drop ./testDb/*
    

安全與認證

  • 使用者授權
每個 MongoDB例項中的資料庫都有許多使用者,
如果啟用了安全性認證後,只有資料庫認證的使用者才可以進行讀寫操作.
MongoDB預設啟動是不驗證使用者名稱和密碼,啟動 MongoDB後可以直接使用 mongo連線上來,
對所有資料庫,都具有root 許可權.所以啟動的時候指定引數,可以阻止客戶端的連線和訪問.
只需要在啟動時指定 --auth 引數即可.此時資料庫當會多一個 admin 庫.

修改配置開啟動使用者許可權認證:
    vim /etc/mongodb.conf      //將auth=true前面的註釋拿掉
    /etc/init.d/mongod restart   //重啟生效

例如:
    我在Mac 中的啟動方式
    mongod --dbpath=/usr/local/Cellar/mongodb/3.4.4/data/ --logpath=/usr/local/Cellar/mongodb/3.4.4/log/log --auth

    此時,使用者如果沒有資料庫許可權, 則連線之後,沒有任何許可權.
  • 使用者授權
新增使用者
mongo V3.0後使用db.createUser()建立使用者;

如下:

> db.createUser(
...   {
...     user: "dba",
...     pwd: "dba",
...     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...   }
... )

ser:使用者名稱

pwd:密碼

roles:指定使用者的角色,可以用一個空陣列給新使用者設定空角色;在roles欄位,可以指定內建角色和使用者定義的角色。role裡的角色可以選:
Built-In Roles(內建角色):
    1. 資料庫使用者角色:read、readWrite;
    2. 資料庫管理角色:dbAdmin、dbOwner、userAdmin;
    3. 叢集管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
    4. 備份恢復角色:backup、restore;
    5. 所有資料庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
    6. 超級使用者角色:root  
    // 這裡還有幾個角色間接或直接提供了系統超級使用者的訪問(dbOwner 、userAdmin、userAdminAnyDatabase)
    7. 內部角色:__system
    
Read:允許使用者讀取指定資料庫
readWrite:允許使用者讀寫指定資料庫
dbAdmin:允許使用者在指定資料庫中執行管理函式,如索引建立、刪除,檢視統計或訪問system.profile
userAdmin:允許使用者向system.users集合寫入,可以找指定資料庫裡建立、刪除和管理使用者
clusterAdmin:只在admin資料庫中可用,賦予使用者所有分片和複製集相關函式的管理許可權。
readAnyDatabase:只在admin資料庫中可用,賦予使用者所有資料庫的讀許可權
readWriteAnyDatabase:只在admin資料庫中可用,賦予使用者所有資料庫的讀寫許可權
userAdminAnyDatabase:只在admin資料庫中可用,賦予使用者所有資料庫的userAdmin許可權
dbAdminAnyDatabase:只在admin資料庫中可用,賦予使用者所有資料庫的dbAdmin許可權。
root:只在admin資料庫中可用。超級賬號,超級許可權


有沒有一個超級許可權?不僅可以授權,而且也可以對集合進行任意操作?答案是肯定的,只是不建議使用。那就是role角色設定成root。

> db.createUser(
...  {
...    user: "zhoujinyi",
...    pwd: "zhoujinyi",
...    roles: [
...       { role: "root", db: "admin" }      #超級root帳號
...    ]
...  }
... )


建立了這麼多帳號,怎麼檢視所有帳號?
 db.system.users.find().pretty()
 
 現在需要建立一個帳號,該賬號需要有grant許可權,即:賬號管理的授權許可權。注意一點,帳號是跟著庫走的,所以在指定庫裡授權,必須也在指定庫裡驗證(auth)。


 > use admin
switched to db admin
> db.createUser(
...   {
...     user: "dba",
...     pwd: "dba",
...     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...   }
... )

  • 使用密碼連線資料庫


  • 許可權管理解釋
在最初始化的時候 MongoDB都預設有一個admin 資料庫,(預設是空的)admin.system.users中將會是儲存具有管理員許可權的使用者.

注意:
    當 admin.system.users中沒有新增任何使用者時,即使MongoDB啟動時新增--auth引數,如果在除admin資料庫中添加了使用者,此時不進行任何認證,依然有使用任何操作,直到你在 admin.system.users中添加了一個使用者.

效能優化

  • explain執行計劃
MongoDB提供了一個explain命令讓我們獲知系統如何處理,查詢請求.利用 explain 命令我們可以很好的觀察系統如何使用索引來加快檢索,同時可以針對優化檢索.

explain 使用案例:
    db.c1.find().explain();
    
  • 優化器profile
MongoDB Database Profile 是一種慢查詢日誌功能,可以作為我們優化資料庫的依據.
開啟 Profile功能
有兩種方式可以控制Profile開關和級別.
啟動MongoDB時加上-profile=級別即可
在客戶端呼叫 db.setProfilingLevel(級別)命令來實時配置,
Profile資訊儲存在system.profile該.我們可以通過db.getProfilingLevel()命令來獲取當前的 Profile級別.
db.getProfilingStatus()獲取當前慢查詢狀態設定.

具體操作:
    db.setProfilingLevel(2); #設定慢操作級別和慢時間定義,單位毫秒(預設100ms)  
    db.getProfilingLevel();  #檢視跟蹤級別
    db.getProfilingStatus(); #檢視當前設定 
    
    上面的profile的級別可以取0,1,2三個值,他們分別表示:
    0 _ 不開啟
    1 _ 記錄慢查詢(預設>100MS)
    2 _ 記錄所有命令

註解:
    Profile 在級別1時會記錄慢命令,上面的預設值為100MS, 有預設就有設定,其設定方法和級別有兩種方法:
        一種是通過新增--slows 啟動引數設定.
        如: --slows=10(單位毫秒)
        
        另一種是db.setProfilingLevel()時加上第二個引數.
        
        db.setProfilingLevel(1,10);
        設定慢操作級別和慢時間定義,單位毫秒(預設100ms) 
        
        那麼這麼慢的定義是什麼?
        可以理解比較耗時的命令,
        如一個查詢耗時10毫秒就會被記錄下來.
        
        

資料庫監控

Mongosniff
    此工具可以從底層監控到底有哪些命令傳送給MongoDB去執行.
    ./mongosniff --source NET lo
    他是實時動態監控的,需要開啟另一個客戶端進行命令操作,可以將這些資料輸出到一個日誌檔案中,那麼就可以儲存下來所有資料庫操作的歷史紀錄.對於後期的效能分析和安全審計等工作將是一個巨大貢獻.
    å


 mongostat
    使用mongo 目錄下的該檔案,進行監控 mongo.
    下面是 執行結果(不分)
    
    
    
mongotop
    使用 mongo 目錄下的該檔案, 用來跟蹤一個MongoDB的例項,檢視哪些大量的時間花費在讀取和寫入資料。 
 

主從複製&副本集.

  • 主從複製 Master-Slave複製(主從)
只需要在某一個伺服器啟動時加上--master引數,而另一個加上--slave與--source引數,即可實現同步.
MongoDB的最新版,已經不推薦使用這種方式了.

具體操作:
    ./mongod --master --dbpath=/usr/local/Cellar/mongodb/3.4.4/data/ --logpath=/usr/local/Cellar/mongodb/3.4.4/log/log --port=2001 --fork
    主伺服器配置
    
    ./mongod --slave --source 127.0.0.1:2001 --dbpath=/usr/local/Cellar/mongodb/3.4.4/data2/ --logpath=/usr/local/Cellar/mongodb/3.4.4/log2/log --port 2002 --fork
    從伺服器配置
    
註釋:
    從伺服器,進入後,show dbs;如果報出錯誤內容:	"errmsg" :"not master and slaveOk=false","code" : 13435,"codeName" : "NotMasterNoSlaveOk"
    使用rs.slaveOk(); 之後即可正常操作.原因:從伺服器上的資料庫是不允許進行讀寫操作,所以就會報類似於這樣的錯誤,這句是解決方法。
    暫未嘗試在設定安全驗證的伺服器中使用 rs.slaveOk();實驗其可不可以用.
        
其它一些配置項: 
    only  從節點---》 指定複製某個資料庫,預設是複製全部資料庫
    slavedelay  從節點---》設定主資料庫同步資料的延遲(單位是秒)
    fastsync 從節點---》以主資料庫的節點快照為節點啟動從資料庫
    autoresync 從節點---》如果不同步則從新同步資料庫
    oplogSize  主節點---》設定oplog的大小(主節點操作記錄儲存到local的oplog中)
    
備註:
    主從備份中,主伺服器是可以增加使用者的,但是從伺服器上不允許增加使用者,會報下面的錯。
    此點還沒有詳細看是不允許增加所有使用者,還是不允許增加超級使用者,暫時先不做研究
    據稱讀寫分離, 主伺服器重啟之後,子伺服器會重新從主伺服器讀取資料,同時清空本伺服器資料.
    所以要做好備份.
    v3.4.4親測
    測試使用停掉子伺服器,刪除主伺服器內容重寫其他內容.結果,資料庫連線後,子伺服器內容,同步.

Replica Sets 複製(副本集)

  • 瞭解副本集
MongoDB 在1.6版本開發了 replica set,主要增加了故障自動切換和自動修復成員節點,各個 DB 之間資料完全一致,最為顯著的區別在於,副本集沒有固定的註解點,他是整個叢集選舉出的一個註解點,在其不工作時變更其他節點,強烈推薦使用.

注意點:
	- 伺服器節點之前時間要同步
	- 開啟防火牆的一定要允許通過
	- 開啟selinux的也要進行設定
	- 建立雙擊互信模式最好不過
  • 部署 Replica Sets 副本集
啟動兩個例項:
	1.建立資料檔案儲存路徑
	mkdir -p /data/data/r0
	mkdir -p /data/data/r1
	2.建立日誌檔案路徑
	mkdir -p /data/log
	3.建立主從 key 檔案用於標識叢集的私鑰的完整路徑,如果各個例項的 key file 內容不一致,程式將不能正常使用.
	mkdir -p /data/key
	echo 'this is key' > /data/key/r0
	echo 'this is key' > /data/key/r1
	chmod 600 /data/key/r*
	4.啟動兩個例項
	./mongod --replSet rsl --keyFile /data/key/r0 --fork --port 2001 --dbpath /data/data/r0 --logpath=/data/log/r0.log --logappend
	
	./mongod --replSet rsl --keyFile /data/key/r1 --fork --port 28011 --dbpath /data/data/r1 --logpath=/data/log/r1.log --logappend
	
	--replSet rsl 副本