一篇文章解決MongoDB的所有問題

目錄

一、MongoDB相關概念

1.1 業務應用場景

傳統的關係型資料庫(如MySQL)。在數作的"三高"需求以及應對Web.0的網站需求面前,顯得力不從心。
解釋:三高「需求:
·High performance-高並發
·Huge Storage-海量數據
·High Scalability&&High Availability-高擴展性和高可用性的需求

1.1.1 而MongoDB可應對「三高”需求·

具體的應用場景:
1)社交場景,使MongoDB存存用戶資訊,以及用戶發表的朋友圈資訊,通過地理位置索引實現跗近的人、地點等功能。
2〕遊戲場景,使用MongoDB存儲遊戲用戶資訊,用戶的裝備、積分等直接以內嵌文檔的形式存儲,方便查詢、高效率存儲和訪問。
3〕物流場景。使用MongoDB存儲訂單資訊,訂單狀態在運送過程中會不斷更新,以MongoDB內嵌數組的形式來存儲,一次查詢就能將訂單所有的變更讀取出來。
4〕物聯網場景,使用MongoDB存儲所有接入的智慧設備資訊,以及設備彙報的日誌資訊,對這些資訊講行多維度的分析·
5)影片直播,使用MongoDB存用戶資訊、點贊互動資訊等。

使用MongoDB共同特點:

1.數據量大
2.寫入操作頻繁
3.價值較低的數據,對事務性要求不高

1.1.2 什麼時候選擇MongoDB?

在架構選型上,除了上述的三個特點外,如果你還猶是否要選擇它?可以考慮以下的一些問題:
應用不需要事務及複雜join支援
新應用,需求會變,數據模型無法確定。想快速迭代開發
應需要2000-3000以上的讀寫QPS(更高也可以)
應用需要TB至PB級別數存儲
應甲發展迅速,需要能快速水平擴展
應甲要求存的數庭不丟失
應需要的99%高可用
應用需要大量的地理位置查詢、文本查詢
如果上述有1個符合,可以考慮MongoDB,2個及以上符合,選懌MongoDB絕不會後悔.

1.1.3 如果用mysql?

相對於mysql,MongoDB可以耕地的成本解決問題(包括學習,開發,運維等成本)

1.1.4MongoDB的特點

1.高性能:索引支援更快的查詢,減少了資料庫系統上的IO活動
2.高可用性:複製工具成為副本集,它可提供自動故障轉移和數據冗餘
3.高擴展性:水平擴展性
4.豐富的查詢支援:支援讀寫,數據聚合,文本搜索和地理空間查詢
5.其他特點:如無模式(動態模式)、靈活的文檔模型

二、MongoDB簡介

 MongoDB是一個開源、高性能、無模式的文檔型資料庫。當初的設計就是用於簡化開發和方便擴展,是nosql(非關係性)資料庫產品中的一種。是最像關係型資料庫(MySQL)的非關係型資料庫。
它支援的數結構非常鬆散,是一種類似於JSON的格式叫BSON,所以它既可以存儲比較複雜的數庭類型,又相當的靈活.
MongoDB中的記錄是一個文檔,它是一個由欄位和值對(field:value)組成的數據結構。MongoDB文檔類似於JSON對象,即一個文檔認為就是一個對象。欄位的數據類型是字元型,它的值除了便用基本的一些類型外,還可以包括其他文檔、普通數組和文檔數組

三、體系結構

Mysql和MongoDB對比

3.1 數據模型

MongoDB的小存儲單位就是文檔(document)對象。文檔(document)對象對應於關係型資料庫的行。數據在MongoDB中以 BSON(Binary-JSON)文檔的格式存儲在磁碟上。
BSON(Binary Serialized Document Format)是一種類json的一種二進位形式的存儲格式,簡稱Binary JSON。BSON和JSON一樣,支援 內嵌的文檔對象和數組對象,但是BSON有JSON沒有的一些數據類型,如Date和BinData類型。 BSON採用了類似於 C 語言結構體的名稱、對表示方法,支援內嵌的文檔對象和數組對象,具有輕量性、可遍歷性、高效性的三個特點,可 以有效描述非結構化數據和結構化數據。這種格式的優點是靈活性高,但它的缺點是空間利用率不是很理想。
Bson中,除了基本的JSON類型:string,integer,boolean,double,null,array和object,mongo還使用了特殊的數據類型。這些類型包括 date,object id,binary data,regular expression 和code。每一個驅動都以特定語言的方式實現了這些類型,查看你的驅動的文檔來獲取詳 細資訊。

BSON數據類型參考列表:

數據類型 描述 舉例
字元串 UTF-8字元串都可表示為字元串類型的數據 {“x” : “foobar”}
對象id 對象id是文檔的12位元組的唯一 ID {“X” :ObjectId() }
布爾值 真或者假:true或者false {“x”:true}+
數組 值的集合或者列表可以表示成數組 {“x” : [“a”, “b”, “c”]}
32位整數 類型不可用。JavaScript僅支援64位浮點數,所以32位整數會被 自動轉換。 shell是不支援該類型的,shell中默認會轉換成64 位浮點數
64位整數 不支援這個類型。shell會使用一個特殊的內嵌文檔來顯示64位 整數 shell是不支援該類型的,shell中默認會轉換成64 位浮點數
64位浮點數 shell中的數字就是這一種類型 {“x”:3.14159,”y”:3}
null 表示空值或者未定義的對象 {“x”:null}
undefined 文檔中也可以使用未定義類型 {“x”:undefined}
符號 shell不支援,shell會將資料庫中的符號類型的數據自動轉換成字元串
正則表達式 文檔中可以包含正則表達式,採用JavaScript的正則表達式語法 {“x” : /foobar/i}
程式碼 文檔中還可以包含JavaScript程式碼 {“x” : function() { /* …… */ }}
二進位數據 二進位數據可以由任意位元組的串組成,不過shell中無法使用
大值/ 小值 BSON包括一個特殊類型,表示可能的大值。shell中沒有這個 類型。

四、官網下載

//www.mongodb.com/download-center/community

據上圖所示下zip包。
提示:版朩的選擇:
MongoDB的版本命名規範如:x.y.z
y為奇數時表示當前版朩為開發版:1.5.2、4.1.13
y為偶數時表示當前版朩為穩定版,如:1.6.3、4.0.10
z是修正板本號,數字越大越好。

五、啟動方式

5.1 命令啟動

第一步:在bin的同級目錄新建data目錄,在data目錄中新建db子目錄。作為存放資料庫文件的位置
第二步:cmd進入bin目錄中,敲:mongod --dbpath=..\data\db  出現以下圖代表成功

5.2 製作系統服務

前提準備:
	(1):log\mongod.log建立存日誌的文件
	(2):E:\mongodb\data\db 建立存數據的文件夾
	(3):把bin目錄配置為環境變數,敲mongo命令登錄連接

將啟動命令,製作為系統服務(開機自啟):	
mongod --bind_ip 0.0.0.0 --port 27017 --logpath E:\mongodb\log\mongod.log --logappend --dbpath E:\mongodb\data\db --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install

5.3 配置文件啟動

第一步:在bin的同級目錄新建conf目錄,在data目錄中新建mongod.cfg文件
第二步:在mongod.conf中寫:dbPath是上面新建存放資料庫文件的位置
	storage:
  		dbPath: E:\mongodb\data\db
第三步:啟動方式(cmd當前在bin目錄下)
	mongod -f ..\conf\mongod.cfg
		或
	mongod --config "E:\mongodb\conf\mongod.cfg"

詳細配置項內容可以參考官方文檔://docs.mongodb.com/manual/reference/configuration-options/

【注意】
1)配置文件中如果使用雙引號,比如路徑地址,自動會將雙引號的內容轉義。如果不轉義,則會報錯:

error-parsing-yaml-config-file-yaml-cpp-error-at-line-3-column-15-unknown-escape-character-d

解決:
a. 對 \ 換成 / 或 \
b. 如果路徑中沒有空格,則無需加引號。 2)配置文件中不能以Tab分割欄位
mongod –dbpath=..\data\db
storage: #The directory where the mongod instance stores its data.Default Value is “\data\db” on Windows. dbPath: D:\02_Server\DBServer\mongodb-win32-x86_64-2008plus-ssl-4.0.1\data

error-parsing-yaml-config-file-yaml-cpp-error-at-line-3-column-15-unknown-escape-character-d
解決:
將其轉換成空格。
更多參數配置:

systemLog:   
	destination: file   
	#The path of the log file to which mongod or mongos should send all diagnostic logging information   
	path: "D:/02_Server/DBServer/mongodb-win32-x86_64-2008plus-ssl-4.0.1/log/mongod.log"   			logAppend: true storage:   
	journal:      
		enabled: true   #The directory where the mongod instance stores its data.Default Value is "/data/db".   
	dbPath: "D:/02_Server/DBServer/mongodb-win32-x86_64-2008plus-ssl-4.0.1/data" net:   
	#bindIp: 127.0.0.1   
	port: 27017 
setParameter:   
	enableLocalhostAuthBypass: false

5.4 Linux系統中的安裝啟動和連接

步驟如下:
(1)先到官網下載壓縮包 mongod-linux-x86_64-4.0.10.tgz 。
(2)上傳壓縮包到Linux中,解壓到當前目錄:

tar -xvf mongodb-linux-x86_64-4.0.10.tgz

(3)移動解壓後的文件夾到指定的目錄中:

mv mongodb-linux-x86_64-4.0.10 /usr/local/mongodb

(4)新建幾個目錄,分別用來存儲數據和日誌:

#數據存儲目錄 
mkdir -p /mongodb/single/data/db 
#日誌存儲目錄 
mkdir -p /mongodb/single/log

(5)新建並修改配置文件

vi /mongodb/single/mongod.conf

配置文件的內容如下:

systemLog:   
	#MongoDB發送所有日誌輸出的目標指定為文件   
	# #The path of the log file to which mongod or mongos should send all diagnostic logging information   
	destination: file   
	#mongod或mongos應向其發送所有診斷日誌記錄資訊的日誌文件的路徑   
	path: "/mongodb/single/log/mongod.log"   
	#當mongos或mongod實例重新啟動時,mongos或mongod會將新條目附加到現有日誌文件的末尾。    
	logAppend: true 
storage:   
	#mongod實例存儲其數據的目錄。storage.dbPath設置僅適用於mongod。   
	##The directory where the mongod instance stores its data.Default Value is "/data/db".   		dbPath: "/mongodb/single/data/db"   
	journal:      
		#啟用或禁用持久性日誌以確保數據文件保持有效和可恢復。      
		enabled: true 
processManagement:   
	#啟用在後台運行mongos或mongod進程的守護進程模式。   
	fork: true 
net:   
	#服務實例綁定的IP,默認是localhost   
	bindIp: localhost,192.168.0.2
	#bindIp   
	#綁定的埠,默認是27017   
	port: 27017

(6)啟動MongoDB服務

[root@bobohost single]# /usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf 
about to fork child process, waiting until server is ready for connections. 
forked process: 90384 
child process started successfully, parent exiting

注意:
如果啟動後不是 successfully ,則是啟動失敗了。原因基本上就是配置文件有問題。

通過進程來查看服務是否啟動了:

[root@bobohost single]# ps -ef |grep mongod 
root      90384      1  0 8月26 ?       00:02:13 /usr/local/mongdb/bin/mongod -f /mongodb/single/mongod.conf

(7)分別使用mongo命令和compass工具來連接測試

提示:如果遠程連接不上,需要配置防火牆放行,或直接關閉linux防火牆

#查看防火牆狀態 
systemctl status firewalld 
#臨時關閉防火牆 systemctl stop firewalld 
#開機禁止啟動防火牆 
systemctl disable firewalld

(8)停止關閉服務

停止服務的方式有兩種:快速關閉和標準關閉,下面依次說明:
(一)快速關閉方法(快速,簡單,數據可能會出錯)
目標:通過系統的kill命令直接殺死進程:
殺完要檢查一下,避免有的沒有殺掉

#通過進程編號關閉節點 
kill -2 54410 

【補充】
如果一旦是因為數據損壞,則需要進行如下操作(了解):
1)刪除lock文件:

rm -f /mongodb/single/data/db/*.lock

2)修複數據:

/usr/local/mongdb/bin/mongod --repair --dbpath=/mongodb/single/data/db

(二)標準的關閉方法(數據不容易出錯,但麻煩):

目標:通過mongo客戶端中的shutdownServer命令來關閉服務
主要的操作步驟參考如下:

 //客戶端登錄服務,注意,這裡通過localhost登錄,如果需要遠程登錄,必須先登錄認證才行。 
 mongo --port 27017 
 //#切換到admin庫 
 use admin 
 //關閉服務 
 db.shutdownServer()

六、Xshell鏈接(Mongo命令)

1.本地連接:在bin目錄中敲mongo。(或者把bin目錄做成環境變數)
2.或者  mongo --host=127.0.0.1 --port=27017

七、Compass-圖形化介面客戶

到MongoDB官網下載MongoDB Compass,

地址://www.mongodb.com/download-center/v2/compass?initial=true
如果是下載安裝版,則按照步驟安裝;如果是下載加壓縮版,直接解壓,執行裡面的 MongoDBCompassCommunity.exe 文件即可。

八、常用基礎命令

8.1 案例需求

存放文章評論的數據存放到MongoDB中,數據結構參考如下:

資料庫:articledb

專欄文章評論 comment
欄位名稱 欄位含義 欄位類型 備註
_id ID Objectld或String Mongo的主鍵欄位
articleid 文章ID String
content 評論的容 String
userid 評論ID String
nickname 評論人昵稱 String
createdatetime 評論的日期時間 Date
likenum 點贊數 int32
replynum 回複數 int32
state 狀態 String 0:不可見;1:可見
parentid 上級ID String 如果為0表示文章的頂級評論

8.2 資料庫操作

8.2.1 選擇和創建資料庫

選擇和創建資料庫的語法格式

use 資料庫名稱

如果如據庫不存在則自動創建,例如:

use test   # 沒有就創建,有就切換

查看有許可權查看的所有的資料庫命令

show dbs
或
show databases

注意:在MongoDB中,集台只有在內容插入後才會創建!就是說,創建集合(數據表)後,必須要再插入一個文檔(記錄),集合才會真正的創建

8.2.2 查看當前正在使用的資料庫命令

db

MongoDB中默認的資料庫為test,如果你沒有選擇資料庫,集合將存放再test資料庫中

8.2.3 默認自帶的三個庫作用

admin: 從許可權的角度來看,這是"root"資料庫。要是將一個用戶添加到這個資料庫,這個用戶自動繼承所有資料庫的許可權。一些特 定的伺服器端命令也只能從這個資料庫運行,比如列出所有的資料庫或者關閉伺服器。 
local: 這個數據永遠不會被複制,可以用來存儲限於本地單台伺服器的任意集合 
config: 當Mongo用於分片設置時,config資料庫在內部使用,用於保存分片的相關資訊

8.2.4 資料庫的刪除

MongoDB 刪除資料庫的語法格式如下:

db.dropDatabase()  # 刪除當前所在的庫

8.3 集合操作

集合,類似關係型資料庫中的表。
可以顯示的創建,也可以隱式的創建。

8.3.1 集合的命名規範:

1.集合名不能是空字元串""。 
2.集合名不能含有\0字元(空字元),這個字元表示集合名的結尾。 
3.集合名不能以"system."開頭,這是為系統集合保留的前綴。 
4.用戶創建的集合名字不能含有保留字元。有些驅動程式的確支援在集合名裡面包含,這是因為某些系統生成的集合中包含該字元。除 非你要訪問這種系統創建的集合,否則千萬不要在名字里出現$。 

8.3.2 集合的顯示創建(了解)

基本語法格式:

db.createCollection(name)    # name: 要創建的集合名稱

eg:創建集合index
	db.createCollection("index")

查看當前庫中的表:show tables命令

show collections 
或 
show tables

8.3.3 集合的隱士創建

當向一個集合中插入一個文檔的時候,如果集合不存在,則會自動創建集合

提示:通常我們使用隱式創建文檔即可。

8.3.4 集合的刪除

集合刪除語法格式如下:

db.collection.drop()
或
db.集合名.drop()

返回值
如果成功刪除選定集合,則 drop() 方法返回 true,否則返回 false

8.4 文檔的基本操作

文檔(document)的數據結構和 JSON 基本一樣。

所有存儲在集合中的數據都是 BSON 格式

8.4.1 文檔鍵命名規範

1)鍵不能含有\0 (空字元)。這個字元用來表示鍵的結尾。 
2)"."點和$有特別的意義,只有在特定環境下才能使用。 
3)以下劃線"_"開頭的鍵是保留的(不是嚴格要求的)。

8.4.2 文檔的插入

(1)單個文檔插入

使用insert() 或 save() 方法向集合中插入文檔,語法如下:insert

db.collection.insert(   
	<document or array of documents>,   
	{     
	writeConcern: <document>,     
	ordered: <boolean>   
	} 
)


#解釋:
	collection:代表集合名稱,如果沒有集合就會隱士創建

參數:

Parameter Type Description
document document or array 要插入到集合中的文檔或文檔數組。(json格式)
writeConcern document Optional. A document expressing the write concern. Omit to use the default write concern. See Write Concern.Do not explicitly set the write concern for the operation if run in a transaction. To use write concern with transactions, see Transactions and Write Concern.
ordered boolean 可選。如果為真,則按順序插入數組中的文檔,如果其中一個文檔出現錯誤,MongoDB將返回而 不處理數組中的其餘文檔。如果為假,則執行無序插入,如果其中一個文檔出現錯誤,則繼續處理 數組中的主文檔。在版本2.6+中默認為true

演示:

要向comment的集合(表)中插入一條測試數據:

db.comment.insert(
{"articleid":"100000","content":"今天天氣真好,陽光明媚","userid":"1001","nickname":"Rose","createdatetime":new Date(),"likenum":NumberInt(10),"state":null}
)

提示:

1)comment集合如果不存在,則會隱式創建 
2)mongo中的數字,默認情況下是double類型,如果要存整型,必須使用函數NumberInt(整型數字),否則取出來就有問題了。
3)插入當前日期使用 new Date()
4)插入的數據沒有指定 _id ,會自動生成主鍵值
5)如果某欄位沒值,可以賦值為null,或不寫該欄位。

執行後,如下,說明插入一個數據成功了。

WriteResult({ "nInserted" : 1 })

(2)批量插入

語法:insertMany

db.collection.insertMany(   
	[ <document 1> , <document 2>, ... ],   
	{      
		writeConcern: <document>,      
		ordered: <boolean>   
	} 
)

參數:

Parameter Type Description
document document or array 要插入到集合中的文檔或文檔數組。(json格式)
writeConcern document Optional. A document expressing the write concern. Omit to use the default write concern. See Write Concern.Do not explicitly set the write concern for the operation if run in a transaction. To use write concern with transactions, see Transactions and Write Concern.
ordered boolean 可選。一個布爾值,指定Mongod實例應執行有序插入還是無序插入。默認為true。

演示:

批量插入多條文章評論:

db.comment.insertMany([    

{"_id":"1","articleid":"100001","content":"我們不應該把清晨浪費在手機上,健康很重要,一杯溫水幸福你我 他。","userid":"1002","nickname":"相忘於江湖","createdatetime":new Date("2019-0805T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},    							  	

{"_id":"2","articleid":"100001","content":"我夏天空腹喝涼開水,冬天喝溫開水","userid":"1005","nickname":"伊人憔 悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},				    

{"_id":"3","articleid":"100001","content":"我一直喝涼開水,冬天夏天都喝。","userid":"1004","nickname":"傑克船 長","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},    

{"_id":"4","articleid":"100001","content":"專家說不能空腹吃飯,影響健康。","userid":"1003","nickname":"凱 撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},    

{"_id":"5","articleid":"100001","content":"研究表明,剛燒開的水千萬不能喝,因為燙 嘴。","userid":"1003","nickname":"凱撒","createdatetime":new Date("2019-0806T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}     
	]);

提示:

插入時指定了 _id ,則主鍵就是該值。
如果某條數據插入失敗,將會終止插入,但已經插入成功的數據不會回滾掉。
因為批量插入由於數據較多容易出現失敗,因此,可以使用try catch進行異常捕捉處理,測試的時候可以不處理。如以下(了解):
try { 
db.comment.insertMany([    
{"_id":"1","articleid":"100001","content":"我們不應該把清晨浪費在手機上,健康很重要,一杯溫水幸福你我 他。","userid":"1002","nickname":"相忘於江湖","createdatetime":new Date("2019-0805T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},  

{"_id":"2","articleid":"100001","content":"我夏天空腹喝涼開水,冬天喝溫開水","userid":"1005","nickname":"伊人憔 悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},   

{"_id":"3","articleid":"100001","content":"我一直喝涼開水,冬天夏天都喝。","userid":"1004","nickname":"傑克船 長","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},    

{"_id":"4","articleid":"100001","content":"專家說不能空腹吃飯,影響健康。","userid":"1003","nickname":"凱 撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},    

{"_id":"5","articleid":"100001","content":"研究表明,剛燒開的水千萬不能喝,因為燙 嘴。","userid":"1003","nickname":"凱撒","createdatetime":new Date("2019-0806T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}     
]);     
} catch (e) {   
print (e); 
}
 

8.4.3 文檔的基本查詢

查詢數據的語法格式如下:

db.collection.find(<query>, [projection])

參數:

Parameter Type Description
query document 可選。使用查詢運算符指定選擇篩選器。若要返回集合中的所有文檔,請省略此參數或傳遞空文檔 ( {} )。
projection document 可選。指定要在與查詢篩選器匹配的文檔中返回的欄位(投影)。若要返回匹配文檔中的所有欄位, 請省略此參數。

演示:

(1)查詢所有

db.comment.find() 
或 
db.comment.find({})

這裡你會發現每條文檔會有一個叫_id的欄位,這個相當於我們原來關係資料庫中表的主鍵,當你在插入文檔記錄時沒有指定該欄位, MongoDB會自動創建,其類型是ObjectID類型。 如果我們在插入文檔記錄時指定該欄位也可以,其類型可以是ObjectID類型,也可以是MongoDB支援的任意類型。

(2)條件查詢

比如我想查詢userid為1003的記錄

db.comment.find({userid:'1003'})

如果你只需要返回符合條件的第一條數據,我們可以使用findOne命令來實現,語法和find一樣

如:查詢用戶編號是1003的記錄,但只多返回符合條件的第一條記錄:

db.comment.findOne({userid:'1003'})

(3)投影查詢

如果要查詢結果返回部分欄位,則需要使用投影查詢(不顯示所有欄位,只顯示指定的欄位)。

1:顯示

0:不顯示

如:查詢結果只顯示 _id、userid、nickname :

>db.comment.find({userid:"1003"},{userid:1,nickname:1}) 
{ "_id" : "4", "userid" : "1003", "nickname" : "凱撒" } 
{ "_id" : "5", "userid" : "1003", "nickname" : "凱撒" }

默認 _id 會顯示。

如:查詢結果只顯示 、userid、nickname ,不顯示 _id :

>db.comment.find({userid:"1003"},{userid:1,nickname:1,_id:0}) 
{ "userid" : "1003", "nickname" : "凱撒" } 
{ "userid" : "1003", "nickname" : "凱撒" }

再例如:查詢所有數據,但只顯示 _id、userid、nickname :

>db.comment.find({},{userid:1,nickname:1,content:1})

8.4.4 文檔的更新

更新文檔的語法:

db.collection.update(query, update, options) 
//或 
db.collection.update(   
<query>,   
<update>,   
    {     
        upsert: <boolean>,     
        multi: <boolean>,     
        writeConcern: <document>,     
        collation: <document>,     
        arrayFilters: [ <filterdocument1>, ... ],     
        hint:  <document|string>        // Available starting in MongoDB 4.2   
    } 
)

(1)覆蓋修改

如果我們想修改_id為1的記錄,點贊量為1001,輸入以下語句:

db.comment.update({_id:"1"},{likenum:NumberInt(1001)})

執行後,我們會發現,這條文檔除了likenum欄位其它欄位都不見

(2)局部修改

$set:

為了解決這個問題,我們需要使用修改器$set來實現,命令如下:

我們想修改_id為2的記錄,瀏覽量為889,輸入以下語句:

db.comment.update({_id:"2"},{$set:{likenum:NumberInt(889)}})

(3)批量修改

{multi:true}

更新所有用戶為 1003 的用戶的昵稱為 凱撒大帝

//默認只修改第一條數據 
db.comment.update({userid:"1003"},{$set:{nickname:"凱撒2"}}) 
//修改所有符合條件的數據 
db.comment.update({userid:"1003"},{$set:{nickname:"凱撒大帝"}},{multi:true})

提示:如果不加後面的參數,則只更新符合條件的第一條記錄

(4)列值增長的修改

如果我們想實現對某列值在原有值的基礎上進行增加或減少,可以使用 $inc 運算符來實現。
需求:對3號數據的點贊數,每次遞增1

db.comment.update({_id:"3"},{$inc:{likenum:NumberInt(1)}})

8.4.5 刪除文檔

刪除文檔的語法結構:

db.集合名稱.remove(條件)

以下語句可以將數據全部刪除,請慎用

db.comment.remove({})

如果刪除_id=1的記錄,輸入以下語句

db.comment.remove({_id:"1"})

8.5 文檔的分頁查詢

8.5.1 統計查詢

統計查詢使用count()方法,語法如下

db.collection.count(query, options)

參數:

query:查詢選擇條件
options:可選。用於修改計數的額外選項

演示:

(1)統計所有記錄

統計comment集合的所有的記錄數:

db.comment.count()

(2)按條件統計記錄數

例如:統計userid為1003的記錄條數

db.comment.count({userid:"1003"})

提示:
默認情況下 count() 方法返回符合條件的全部記錄條數

8.5.2 分頁列表查詢

可以使用limit()方法來讀取指定數量的數據,使用skip()方法來跳過指定數量的數據。

基本語法如下所示

>db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

(1)limit限制查詢條數

如果你想返回指定條數的記錄,可以在find方法後調用limit來返回結果(TopN),默認值20,例如:

db.comment.find().limit(3)  # 查詢前3條記錄

(2)skip跳過條數

skip方法同樣接受一個數字參數作為跳過的記錄條數。(前N個不要),默認值是0

db.comment.find().skip(3)  # 跳過前3條

(3)分頁查詢

每頁2個,第二頁開始:跳過前兩條數據,接著值顯示3和4條數據

//第一頁 db.comment.find().skip(0).limit(2) 
//第二頁 db.comment.find().skip(2).limit(2) 
//第三頁 db.comment.find().skip(4).limit(2)

8.5.3 排序查詢

sort() 方法對數據進行排序,sort() 方法可以通過參數指定排序的欄位,並使用 1 和 -1 來指定排序的方式,其中 1 為升序排列,而 -1 是用 於降序排列。

語法如下:

db.COLLECTION_NAME.find().sort({KEY:1}) 
或 
db.集合名稱.find().sort(排序方式)

例如:
對userid降序排列,並對訪問量進行升序排列

db.comment.find().sort({userid:-1,likenum:1})

提示:
skip(), limilt(), sort()三個放在一起執行的時候,執行的順序是先 sort(), 然後是 skip(),後是顯示的 limit(),和命令編寫順序無關。

8.6 文檔的更多查詢

8.6.1 正則複雜查詢

MongoDB的模糊查詢是通過正則表達式的方式實現的。格式為:

db.collection.find({field:/正則表達式/}) 
或 
db.集合.find({欄位:/正則表達式/})

提示:正則表達式是js的語法,直接量的寫法

例如,我要查詢評論內容包含「開水」的所有文檔,程式碼如下:

db.comment.find({content:/開水/})

如果要查詢評論的內容中以「專家」開頭的,程式碼如下:

db.comment.find({content:/^專家/})

8.6.2 比較查詢

<, <=, >, >= 這個操作符也是很常用的,格式如下:

db.集合名稱.find({ "field" : { $gt: value }}) // 大於: field > value db.集合名稱.find({ "field" : { $lt: value }}) // 小於: field < value db.集合名稱.find({ "field" : { $gte: value }}) // 大於等於: field >= value db.集合名稱.find({ "field" : { $lte: value }}) // 小於等於: field <= value db.集合名稱.find({ "field" : { $ne: value }}) // 不等於: field != value

示例:查詢評論點贊數量大於700的記錄

db.comment.find({likenum:{$gt:NumberInt(700)}})

8.6.3 包含查詢

包含使用$in操作符。 示例:查詢評論的集合中userid欄位包含1003或1004的文檔

db.comment.find({userid:{$in:["1003","1004"]}})

不包含使用$nin操作符。 示例:查詢評論集合中userid欄位不包含1003和1004的文檔

db.comment.find({userid:{$nin:["1003","1004"]}})

8.6.4 條件連接查詢

我們如果需要查詢同時滿足兩個以上條件,需要使用$and操作符將條件進行關聯。(相 當於SQL的and) 格式為:

$and:[ {  },{  },{ } ]

示例:查詢評論集合中likenum大於等於700 並且小於2000的文檔:

db.comment.find({$and:[{likenum:{$gte:NumberInt(700)}},{likenum:{$lt:NumberInt(2000)}}]})

如果兩個以上條件之間是或者的關係,我們使用 操作符進行關聯,與前面 and的使用方式相同 格式為

$or:[ {  },{  },{   } ]

示例:查詢評論集合中userid為1003,或者點贊數小於1000的文檔記錄

db.comment.find({$or:[ {userid:"1003"} ,{likenum:{$lt:1000} }]})

8.7 常用命令小結

選擇切換資料庫:use 庫名
插入數據:db.comment.insert({bson數據}) 
查詢所有數據:db.comment.find(); 
條件查詢數據:db.comment.find({條件}) 
查詢符合條件的第一條記錄:db.comment.findOne({條件}) 
查詢符合條件的前幾條記錄:db.comment.find({條件}).limit(條數) 
查詢符合條件的跳過的記錄:db.comment.find({條件}).skip(條數) 
修改數據:db.comment.update({條件},{修改後的數據}) 或db.comment.update({條件},{$set:{要修改部分的欄位:數據}) 
修改數據並自增某欄位值:db.comment.update({條件},{$inc:{自增的欄位:步進值}}) 
刪除數據:db.comment.remove({條件}) 
統計查詢:db.comment.count({條件}) 
模糊查詢:db.comment.find({欄位名:/正則表達式/}) 
條件比較運算:db.comment.find({欄位名:{$gt:值}}) 
包含查詢:db.comment.find({欄位名:{$in:[值1,值2]}})或db.comment.find({欄位名:{$nin:[值1,值2]}}) 
條件連接查詢:db.comment.find({$and:[{條件1},{條件2}]})或db.comment.find({$or:[{條件1},{條件2}]})
 

九、索引

.1 索引概述

索引支援在MongoDB中高效地執行查詢。如果沒有索引,MongoDB必須執行全集合掃描,即掃描集合中的每個文檔,以選擇與查詢語句 匹配的文檔。這種掃描全集合的查詢效率是非常低的,特別在處理大量的數據時,查詢可以要花費幾十秒甚至幾分鐘,這對網站的性能是非 常致命的。
如果查詢存在適當的索引,MongoDB可以使用該索引限制必須檢查的文檔數。
索引是特殊的數據結構,它以易於遍歷的形式存儲集合數據集的一小部分。索引存儲特定欄位或一組欄位的值,按欄位值排序。索引項的排 序支援有效的相等匹配和基於範圍的查詢操作。此外,MongoDB還可以使用索引中的排序返回排序結果。

官網文檔://docs.mongodb.com/manual/indexes/
了解:
MongoDB索引使用B樹數據結構(確切的說是B-Tree,MySQL是B+Tree)

9.2 索引的類型

9.2.1 單欄位索引

MongoDB支援在文檔的單個欄位上創建用戶定義的升序/降序索引,稱為單欄位索引(Single Field Index)。 對於單個欄位索引和排序操作,索引鍵的排序順序(即升序或降序)並不重要,因為MongoDB可以在任何方向上遍歷索引。

9.2.2 複合索引

MongoDB還支援多個欄位的用戶定義索引,即複合索引(Compound Index)。

複合索引中列出的欄位順序具有重要意義。例如,如果複合索引由 { userid: 1, score: -1 } 組成,則索引首先按userid正序排序,然後 在每個userid的值內,再在按score倒序排序。

9.2.3 其他索引

地理空間索引(Geospatial Index)、文本索引(Text Indexes)、哈希索引(Hashed Indexes)。

為了支援對地理空間坐標數據的有效查詢,MongoDB提供了兩種特殊的索引:返回結果時使用平面幾何的二維索引和返回結果時使用球面 幾何的二維球面索引。

9.3 索引管理操作

9.3.1 索引的查看

db.集合名.getIndexes()


[
        {
                "v" : 2,        # mongodb引擎的版本號(不用管)
                "key" : {
                        "_id" : 1       # 默認主鍵
                },
                "name" : "_id_",         # 索引名稱
                "ns" : "jeff.comment"    # 索引的位置
        }
]

9.3.2 創建索引

db.集合名.createIndex(keys, options)
參數:
keys:包含欄位和值對的文檔,其中欄位是索引鍵,值描述該欄位的索引類型。對於欄位上的升序索引,請 指定值1;對於降序索引,請指定值-1。比如: {欄位:1或-1} ,其中1 為指定按升序創建索引,如果你 想按降序來創建索引指定為 -1 即可。另外,MongoDB支援幾種不同的索引類型,包括文本、地理空 間和哈希索引。
options:可選。包含一組控制索引創建的選項的文檔。有關詳細資訊,請參見選項詳情列表。

options(更多選項)列表:

Parameter Type Description
background Boolean 建索引過程會阻塞其它資料庫操作,background可指定以後台方式創建索引,即增加 “background” 可選參數。”background” 默認值為false。
unique Boolean 建立的索引是否唯一。指定為true創建唯一索引。默認值為false.
name string 索引的名稱。如果未指定,MongoDB的通過連接索引的欄位名和排序順序生成一個索引名 稱。
dropDups Boolean 3.0+版本已廢棄。在建立唯一索引時是否刪除重複記錄,指定 true 創建唯一索引。默認值為 false.
sparse Boolean 對文檔中不存在的欄位數據不啟用索引;這個參數需要特別注意,如果設置為true的話,在索 引欄位中不會查詢出不包含對應欄位的文檔.。默認值為 false.
expireAfterSeconds integer 指定一個以秒為單位的數值,完成 TTL設定,設定集合的生存時間。
v index version 索引的版本號。默認的索引版本取決於mongod創建索引時運行的版本。
weights document 索引權重值,數值在 1 到 99,999 之間,表示該索引相對於其他索引欄位的得分權重。
default_language string 對於文本索引,該參數決定了停用詞及詞幹和詞器的規則的列表。 默認為英語
language_override string 對於文本索引,該參數指定了包含在文檔中的欄位名,語言覆蓋默認的language,默認值為 language.

提示:
注意在 3.0.0 版本前創建索引方法為 db.collection.ensureIndex() ,之後的版本使用了 db.collection.createIndex() 方法, ensureIndex() 還能用,但只是 createIndex() 的別名。

演示:

(1)創建單欄位索引

對 userid 欄位建立索引

db.comment.createIndex({userid:1})   # 升序

# 查看一下索引
db.comment.getIndexes()

(2)創建符合索引

對 userid 和 nickname 同時建立複合(Compound)索引:

db.comment.createIndex({userid:1,nickname:-1})

# 查看一下索引
db.comment.getIndexes()

9.3.3 刪除索引

(1)指定索引刪除

db.集合名.dropIndex(索引)
eg:
db.comment.dropIndex({userid:1})  # 刪除{userid:1}索引

(2)刪除所有索引

_id索引永遠不會被刪除

db.集合名.dropIndexes()
eg:
db.comment.dropIndexes()   # 刪除comment集合的所有索引

9.4 索引的使用

9.4.1 執行計劃

分析查詢性能 通常使用執行計劃來查看查詢的情況,如查詢耗費的時間、是 否基於索引查詢等。

那麼,通常,我們想知道,建立的索引是否有效,效果如何,都需要通過執行計劃查看。

db.集合名.find(query,options).explain(options)
eg:
db.comment.find({userid:"1003"}).explain()   # 查看根據userid查詢數據的情況
"stage" : "COLLSCAN",   # 全局掃描

"stage" : "FETCH",   # 抓取

(1)沒有索引的情況

(2)有索引的情況

9.4.2 覆蓋查詢