MongoDB常用操作

# MongoDB

## 數(shù)據(jù)庫(kù)分類(lèi)

### 關(guān)系型數(shù)據(jù)庫(kù)

* 具備ACID特性

? ? * Atomic原子性,也就是說(shuō)事務(wù)里的所有操作要么全部做完,要么都不做,事務(wù)成功的條件是事務(wù)里的所有操作都成功,只要有一個(gè)操作失敗,整個(gè)事務(wù)就失敗,需要回滾。*比如銀行轉(zhuǎn)賬,從A賬戶轉(zhuǎn)100元至B賬戶,分為兩個(gè)步驟:1)從A賬戶取100元;2)存入100元至B賬戶。這兩步要么一起完成,要么一起不完成,如果只完成第一步,第二步失敗,錢(qián)會(huì)莫名其妙少了100元。*

? ? * Consistency一致性,也就是說(shuō)數(shù)據(jù)庫(kù)要一直處于一致的狀態(tài),事務(wù)的運(yùn)行不會(huì)改變數(shù)據(jù)庫(kù)原本的一致性約束。*例如現(xiàn)有完整性約束a+b=10,如果一個(gè)事務(wù)改變了a,那么必須得改變b,使得事務(wù)結(jié)束后依然滿足a+b=10,否則事務(wù)*失敗。

? ? * Isolation獨(dú)立性,所謂的獨(dú)立性是指并發(fā)的事務(wù)之間不會(huì)互相影響,如果一個(gè)事務(wù)要訪問(wèn)的數(shù)據(jù)正在被另外一個(gè)事務(wù)修改,只要另外一個(gè)事務(wù)未提交,它所訪問(wèn)的數(shù)據(jù)就不受未提交事務(wù)的影響。*比如現(xiàn)在有個(gè)交易是從A賬戶轉(zhuǎn)100元至B賬戶,在這個(gè)交易還未完成的情況下,如果此時(shí)B查詢自己的賬戶,是看不到新增加的100元的。*

? ? * Durability持久性,持久性是指一旦事務(wù)提交后,它所做的修改將會(huì)永久的保存在數(shù)據(jù)庫(kù)上,即使出現(xiàn)宕機(jī)也不會(huì)丟失。

* 局限性和不適用場(chǎng)景

? ? * 關(guān)系型數(shù)據(jù)庫(kù)為了維護(hù)一致性所付出的巨大代價(jià)就是其讀寫(xiě)性能比較差。在網(wǎng)頁(yè)應(yīng)用中,尤其是SNS(社交)應(yīng)用中,一致性卻不是顯得那么重要,用戶A看到的內(nèi)容和用戶B看到同一用戶C內(nèi)容更新不一致是可以容忍的,或者說(shuō),兩個(gè)人看到同一好友的數(shù)據(jù)更新的時(shí)間差那么幾秒是可以容忍的,因此,關(guān)系型數(shù)據(jù)庫(kù)的最大特點(diǎn)在這里已經(jīng)無(wú)用武之地,起碼不是那么重要了。

? ? * 關(guān)系數(shù)據(jù)庫(kù)的另一個(gè)特點(diǎn)就是其具有固定的表結(jié)構(gòu),因此,其擴(kuò)展性比較差,而在SNS中,系統(tǒng)的升級(jí),功能的增加,往往意味著數(shù)據(jù)結(jié)構(gòu)巨大變動(dòng),這一點(diǎn)關(guān)系型數(shù)據(jù)庫(kù)也難以應(yīng)付,需要新的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)。

### **非關(guān)系型數(shù)據(jù)庫(kù) NoSQL(Not Only SQL )**

*? NoSQL數(shù)據(jù)庫(kù)的四大分類(lèi)

|分類(lèi) |舉例 |典型應(yīng)用場(chǎng)景 |數(shù)據(jù)模型 |優(yōu)點(diǎn) |缺點(diǎn) |

|--- |--- |--- |--- |--- |--- |

|鍵值(key-value)存儲(chǔ)數(shù)據(jù)庫(kù) |Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB |內(nèi)容緩存,主要用于處理大量數(shù)據(jù)的高訪問(wèn)負(fù)載,也用于一些日志系統(tǒng)等等。 |Key 指向 Value 的鍵值對(duì),通常用hash table來(lái)實(shí)現(xiàn) |查找速度快 |數(shù)據(jù)無(wú)結(jié)構(gòu)化,通常只被當(dāng)作字符串或者二進(jìn)制數(shù)據(jù) |

|--- |--- |--- |--- |--- |--- |

|**列存儲(chǔ)數(shù)據(jù)庫(kù)** |Cassandra, HBase, Riak |分布式的文件系統(tǒng) |以列簇式存儲(chǔ),將同一列數(shù)據(jù)存在一起 |查找速度快,可擴(kuò)展性強(qiáng),更容易進(jìn)行分布式擴(kuò)展 |功能相對(duì)局限 |

|**文檔型數(shù)據(jù)庫(kù)** |CouchDB, MongoDb |Web應(yīng)用(與Key-Value類(lèi)似,Value是結(jié)構(gòu)化的,不同的是數(shù)據(jù)庫(kù)能夠了解Value的內(nèi)容) |Key-Value對(duì)應(yīng)的鍵值對(duì),Value為結(jié)構(gòu)化數(shù)據(jù) |數(shù)據(jù)結(jié)構(gòu)要求不嚴(yán)格,表結(jié)構(gòu)可變,不需要像關(guān)系型數(shù)據(jù)庫(kù)一樣需要預(yù)先定義表結(jié)構(gòu) |查詢性能不高,而且缺乏統(tǒng)一的查詢語(yǔ)法。 |

|**圖形(Graph)數(shù)據(jù)庫(kù)** |Neo4J, InfoGrid, Infinite Graph |社交網(wǎng)絡(luò),推薦系統(tǒng)等。專注于構(gòu)建關(guān)系圖譜 |圖結(jié)構(gòu) |利用圖結(jié)構(gòu)相關(guān)算法。比如最短路徑尋址,N度關(guān)系查找等 |很多時(shí)候需要對(duì)整個(gè)圖做計(jì)算才能得出需要的信息,而且這種結(jié)構(gòu)不太好做分布式的集群方案。 |

* Mongodb

? ? * 是文檔型的非關(guān)系型數(shù)據(jù)庫(kù),使用bson( Binary Serialized Document Format) 結(jié)構(gòu)。其優(yōu)勢(shì)在于查詢功能比較強(qiáng)大,能存儲(chǔ)海量數(shù)據(jù)。

# Mac OSX 平臺(tái)安裝Mongo

## 使用 brew 下載并安裝

1、終端輸入:brew install mongodb

2、安裝成功后可以看到提示:

```

To have launchd start mongodb now and restart at login:

? brew services start mongodb

Or, if you don't want/need a background service you can just run:

? mongod --config /usr/local/etc/mongod.conf

==> Summary

??? /usr/local/Cellar/mongodb/4.0.0: 18 files, 268.4MB

```

## 運(yùn)行mongoDB服務(wù)

1、首先創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)存儲(chǔ)目錄 /data/db,命令行輸入:sudo mkdir -p /data/db

2、創(chuàng)建日志文件:sudo vim /data/db/mongo.log;創(chuàng)建pid文件:sudo vim /var/run/mongo.pid

3、啟動(dòng) mongodb,分兩種啟動(dòng)方式:

* 啟動(dòng)命令直接指定命令參數(shù)方式:sudo mongod -port 27017 -dbpath /data/db -fork? -pidfilepath=/var/run/mongo.pid? -logpath /data/db/mongo.log

* 啟動(dòng)命令指定配置文件方式:

? ? * 1、創(chuàng)建配置文件 :sudo vim /etc/mongodb.conf?


? ? *? ? 2、執(zhí)行:sudo mongo -f /etc/mongodb.conf

* 啟動(dòng)參數(shù)說(shuō)明(可以通過(guò)mongo -help來(lái)查看全部參數(shù)):

? ? * -port arg? ? #指定服務(wù)端口號(hào),默認(rèn)端口27017。

? ? * -dbpath? ? #? 指定存儲(chǔ)路徑。

? ? * -logpath arg? ? # 指定MongoDB日志文件,注意是指定文件不是目錄。使用fork參數(shù)時(shí)因?yàn)槿罩緹o(wú)法寫(xiě)到控制臺(tái),所以需要同時(shí)使用logpath參數(shù)。

? ? * -pidfilepath arg? ? # 指定PID File 的完整路徑,如果沒(méi)有設(shè)置,則沒(méi)有PID文件。

? ? * -fork? ? # 以守護(hù)進(jìn)程的方式運(yùn)行MongoDB,相當(dāng)于nohup “shell”? &用法。使用fork參數(shù)時(shí)因?yàn)槿罩緹o(wú)法寫(xiě)到控制臺(tái),所以需要同時(shí)使用logpath參數(shù)。

? ? * -directoryperdb? ? # 設(shè)置每個(gè)數(shù)據(jù)庫(kù)將被保存在一個(gè)單獨(dú)的目錄

? ? * -maxConns arg? # 最大同時(shí)連接數(shù) 默認(rèn)2000

? ? * -auth? ? #用戶認(rèn)證,默認(rèn)false,當(dāng)設(shè)置為true時(shí)候,進(jìn)入數(shù)據(jù)庫(kù)需要auth驗(yàn)證,當(dāng)數(shù)據(jù)庫(kù)里沒(méi)有用戶,則不需要驗(yàn)證也可以操作。直到創(chuàng)建了第一個(gè)用戶,之后操作都需要驗(yàn)證。

啟動(dòng)成功后可以看到以下提示:

```

[initandlisten] waiting for connections on port 27017

forked process: 41540

child process started successfully, parent exiting

```

## 停止mongoDB服務(wù)

正常關(guān)閉方式:

* 前臺(tái)方式啟動(dòng)時(shí),命令行光標(biāo)鍵入CTRL+C

* 通過(guò)連接的客戶端關(guān)閉,首先連接mongo成功后

? ? * 第一步:use admin

? ? * 第二步:db.shutdownServer()

異常關(guān)閉再次啟動(dòng)報(bào)錯(cuò)時(shí):

* 使用kill進(jìn)程方式

? ? * ps -ef |grep mongo

? ? * kill -15 pid? ? #建議不要使用 ”kill -9 pid“,因?yàn)槿绻\(yùn)行在沒(méi)開(kāi)啟日志(—journal)的情況下,可能會(huì)造成數(shù)據(jù)損失。

> 注意:在mongodb的啟動(dòng)時(shí),在數(shù)據(jù)目錄下,會(huì)生成一個(gè)mongod.lock文件。如果在正常退出時(shí),會(huì)清除這個(gè)mongod.lock文件,若是異常退出,在下次啟動(dòng)的時(shí)候,會(huì)禁止啟動(dòng),并看到下面的報(bào)錯(cuò)。

```

? ? exception in initAndListen: DBPathInUse: Unable to lock the lock file:

? ? /data/db/mongod.lock (Resource temporarily unavailable). Another mongod instance is already running on the /data/db directory, terminating

```

## Mongo連接

### 客戶端連接

語(yǔ)法格式:mongo 遠(yuǎn)程主機(jī)ip或DNS:端口號(hào)/數(shù)據(jù)庫(kù)名 -u user -p password

例:連接本地?cái)?shù)據(jù)庫(kù),在終端窗口輸入:mongo

```

~ ? mongo

MongoDB shell version v4.0.0

connecting to: mongodb://127.0.0.1:27017

MongoDB server version: 4.0.0

```

例:連接遠(yuǎn)程sit環(huán)境mongo數(shù)據(jù)庫(kù)

```

~ ? mongo 10.4.12.78/admin -u sit-user -p xxxxA5

MongoDB shell version v4.0.0

connecting to: mongodb://10.4.12.78:27017/admin

MongoDB server version: 3.2.12

```

### 標(biāo)準(zhǔn)uri連接

語(yǔ)法格式:mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

```

`#!/usr/bin/env python

``# -*- coding:utf-8 -*-

from pymongo import MongoClient

uri = 'mongodb://sit-user:xxxxqA5@10.4.12.78/admin'

con = MongoClient(uri)`

```

# MongoDB語(yǔ)法

## 概念術(shù)語(yǔ)

|SQL術(shù)語(yǔ)/概念 |MongoDB術(shù)語(yǔ)/概念 |解釋/說(shuō)明 |

|--- |--- |--- |

|database |database |數(shù)據(jù)庫(kù) |

|--- |--- |--- |

|table |collection |數(shù)據(jù)庫(kù)表/集合 |

|row |document |數(shù)據(jù)記錄行/文檔 |

|column |field |數(shù)據(jù)字段 |

|index |index |索引 |

|primary key |primary key |主鍵,MongoDB自動(dòng)將_id字段設(shè)置為主鍵 |


## 數(shù)據(jù)庫(kù)操作

### 創(chuàng)建數(shù)據(jù)庫(kù)

1、語(yǔ)法格式:use <database_name>? ? #如果數(shù)據(jù)庫(kù)存在時(shí)會(huì)切換到該數(shù)據(jù)庫(kù),不存在時(shí)會(huì)創(chuàng)建該數(shù)據(jù)庫(kù)。

2、操作成功后可以看到提示:

```

> use sms

switched to db sms

```

### 刪除數(shù)據(jù)庫(kù)

1、語(yǔ)法格式:db.dropDatabase()? ? #刪除當(dāng)前使用的數(shù)據(jù)庫(kù),可以通過(guò)命令“db”來(lái)查看當(dāng)前數(shù)據(jù)庫(kù)

2、操作成功后可以看到提示:

```

> db? ? #查看當(dāng)前數(shù)據(jù)庫(kù)

sms

> db.dropDatabase()

{ "ok" : 1 }

```

## 集合操作

### 創(chuàng)建集合

1、語(yǔ)法格式:db.createCollection(<name>,{ <options>})? ? #name為要?jiǎng)?chuàng)建的集合名,options為可選參數(shù):

* capped? ? #布爾類(lèi)型,如果為 true,則創(chuàng)建固定集合。固定集合是指有著固定大小的集合,當(dāng)達(dá)到最大值時(shí),它會(huì)自動(dòng)覆蓋最早的文檔。當(dāng)該值為 true 時(shí),必須指定 size 參數(shù)。

* size? ? #數(shù)值,為固定集合指定一個(gè)最大值(以字節(jié)計(jì))。如果 capped 為 true,也需要指定該字段**。**

* max? ? #數(shù)值,指定固定集合中包含文檔的最大數(shù)量。

2、執(zhí)行:db.createCollection("seller",{ capped : true, size :6142800, max : 10000 },創(chuàng)建集合成功后可以看到提示:

```

> db? ? #查看當(dāng)前數(shù)據(jù)庫(kù)

sms

> db.createCollection("seller",{ capped : true, size :6142800, max : 10000 })

{ "ok" : 1 }

```

### 刪除集合

1、語(yǔ)法格式:db.collection_name.drop()

2、刪除集合成功后,可以看到命令行返回“true”,否則返回“false”。

```

> show collections? ? #查看當(dāng)前數(shù)據(jù)庫(kù)下的集合

ark_open_api_account

seller

> db.ark_open_api_account.drop()

true

> show collections

seller

```

## 文檔操作

### 創(chuàng)建文檔

1、語(yǔ)法格式:db.collection_name.insert(<document>)

2、執(zhí)行db.seller.insert({"role" : "partner","shopname" : "redqa009-測(cè)試","email" : "[xx@163.com](mailto:xx@163.com)"})?

```

> db.seller.insert({"role" : "partner","shopname" : "redqa009-測(cè)試","email" : "[xx@163.com](mailto:xx@163.com)"})

WriteResult({ "nInserted" : 1 })

> db.seller.find()? ? #查詢文檔

{ "_id" : ObjectId("5b554bd275f30ccd39ca6483"), "role" : "partner", "shopname" : "redqa009-測(cè)試", "email" : "xx@163.com" }

```

或? 先定義document后再執(zhí)行insert(document)

```

> document=([{"role" : "partner","shopname" : "redqa007品牌店","email" : "1401261542@qq.com"},{"role" : "partner","shopname" : "redqa018","email" : "qatest6@redqa.xyz"}])

[

{

"role" : "partner",

"shopname" : "redqa007品牌店",

"email" : "1401261542@qq.com"

},

{

"role" : "partner",

"shopname" : "redqa018",

"email" : "[qatest6@redqa.xyz](mailto:qatest6@redqa.xyz)"

}

]

> db.seller.insert(document)

BulkWriteResult({

"writeErrors" : [ ],

"writeConcernErrors" : [ ],

"nInserted" : 2,

"nUpserted" : 0,

"nMatched" : 0,

"nModified" : 0,

"nRemoved" : 0,

"upserted" : [ ]

})

> db.seller.find()

{ "_id" : ObjectId("5b554bd275f30ccd39ca6483"), "role" : "partner", "shopname" : "redqa009-測(cè)試", "email" : "[xx@163.com](mailto:xx@163.com)" }

{ "_id" : ObjectId("5b554ee875f30ccd39ca6484"), "role" : "partner", "shopname" : "redqa007品牌店", "email" : "xx@qq.com" }

{ "_id" : ObjectId("5b554ee875f30ccd39ca6485"), "role" : "partner", "shopname" : "redqa018","email" : "xxx@redqa.xyz" }

```

### 更新文檔

* update()方法

? ? * 1、語(yǔ)法格式:

```

db.collection.update(

<query>,

<update>,

{

upsert: <boolean>,? # 可選,含義為如果不存在update的記錄,是否插入objNew,true為插入,默認(rèn)是false,不插入。

multi: <boolean>,? # 可選,默認(rèn)是false,只更新找到的第一條記錄,如果這個(gè)參數(shù)為true,就把按條件查出來(lái)多條記錄全部更新。

writeConcern: <document>? # writeConcern** **:可選,拋出異常的級(jí)別。

}

)

```

? ? * 2、更新shopname為"redqa009-測(cè)試1”商家的郵箱

? ? * 執(zhí)行'db.seller.update({shopname:"redqa009-測(cè)試1"},{$set:{email:"xx@163.com"}},{upsert:true})'

```

> db.seller.find()

{ "_id" : ObjectId("5b554bd275f30ccd39ca6483"), "role" : "partner", "shopname" : "redqa009-測(cè)試", "email" : "lxx@163.com" }

{ "_id" : ObjectId("5b554ee875f30ccd39ca6484"), "role" : "partner", "shopname" : "redqa007品牌店", "email" : "xx@qq.com" }

{ "_id" : ObjectId("5b554ee875f30ccd39ca6485"), "role" : "partner", "shopname" : "redqa018", "email" : "xx@redqa.xyz" }

> db.seller.update({shopname:"redqa009-測(cè)試1"},{$set:{email:"xx@163.com"}},{upsert:true})

WriteResult({

? ? "nMatched" : 0,

? ? "nUpserted" : 1,

? ? "nModified" : 0,

? ? "_id" : ObjectId("5b556dca30563a38f0284e00")

})

```

> 注意:當(dāng)集合為Capped collection時(shí),如果更新或替換操作更改了文檔大小,則操作將失敗。錯(cuò)誤提示如下:

```

WriteResult({

? ? "nMatched" : 0,

? ? "nUpserted" : 0,

? ? "nModified" : 0,

? ? "writeError" : {

? ? ? ? "code" : 10003,

? ? ? ? "errmsg" : "Cannot change the size of a document in a capped collection: 79 != 77"

? ? }

})

```

* save()方法

? ? * 1、語(yǔ)法格式

```

db.collection.save(

? <document>,? ? # 根據(jù)文檔中的'_id'字段,找到一個(gè)已經(jīng)存在的文檔,進(jìn)行更新。

? {

? ? writeConcern: <document>

? }

)

```

> 補(bǔ)充:

> 當(dāng)文檔中包含'_id'字段,但匹配不到已存在的文檔,也會(huì)將文檔插入數(shù)據(jù)庫(kù)。

> 當(dāng)文檔中不含'_id'字段,save方法將調(diào)用insert方法,插入這條文檔并分配一個(gè)_id。

### 刪除文檔

1、語(yǔ)法格式:

```

db.collection.remove(

? <query>,? ? # 可選,刪除的文檔的條件。

? {

? ? justOne: <boolean>,? ? # 可選,如果設(shè)為 true 或 1,則只刪除一個(gè)文檔。

? ? writeConcern: <document>

? }

)

```

> 注意:Capped collection不允許使用remove()方法刪除,只能使用db.collection.drop()方法刪除集合。db.collection.isCapped() 命令可以查看一個(gè)集合是否是 Capped Collection。

### 查詢文檔

```

1、db.collection.find(query, projection) # 可選,query為查詢條件,可選,projection指定返回的鍵。

```

### 比較操作符

* 大于:$gt

* 大于等于:$gte

* 小于:$lt

* 小于等于:$lte

* 等于:$eq

例:查詢訂單“total_discounted_price”大于等于100并且小于等于200的任意一個(gè)訂單號(hào)。

```

db.order.findOne({total_discounted_price:{$gte:150,$lte:200}},{order_id:1})

#projection:1代表只返回指定字段,為0代表不返回該字段。

```

* 不等于:$ne

例:查詢商家("seller":"53df5710b4c4d6383ae8e9a6")任意一個(gè)不是“已取消”的訂單

```

db.order_package.find({"seller":"53df5710b4c4d6383ae8e9a6","status":{$ne:998}})

```

* 匹配數(shù)組中任意值:$in

例:查詢所有訂單狀態(tài)狀態(tài)為“待配貨”、“配貨中”或“已發(fā)貨”的訂單。

```

db.order_package.find({ "status": {$in:[4,5,6]}})

```

* 不匹配數(shù)組中任意值:$nin

### 邏輯操作符

* 與查詢:$and

例:查詢商家("seller":"53df5710b4c4d6383ae8e9a6")所有訂單狀態(tài)狀態(tài)為“待配貨”、“配貨中”或“已發(fā)貨”的訂單。

```

db.order_package.find({$and:[{"seller":"53df5710b4c4d6383ae8e9a6"},{"status": {$in:[4,5,6]}}]})

等同于

db.order_package.find({ "seller":"53df5710b4c4d6383ae8e9a6","status": {$in:[4,5,6]}})

```

* 或查詢:$or

例:查詢訂單“total_discounted_price”小于等于100或大于等于200的訂單號(hào)。

```

db.order.find({$or:[{total_discounted_price:{$lte:100}},{total_discounted_price:{$gte:200}}]})

```

### 元素操作符

* 查詢是否存在某字段:$exists

例:查詢維護(hù)了貿(mào)易模式的所有商家。

```

db.seller.find({ "trade_mode":{$exists:true} })

```

*? 查詢數(shù)組中元素是否滿足指定的條件:$elemMatch

例:查詢所有支持“red_bonded”物流模式的商家。

```

被查詢集合的數(shù)據(jù)結(jié)構(gòu):

{

? "_id": ObjectId("5a151d9deb90b912e76ee832"),

? "shopname": "redqa009-測(cè)試",

? "logistics_infos": [

? ? {

? ? ? "name": "red_auto",

? ? ? "logistics": "auto",

? ? ? "is_default": true

? ? },

? ? {

? ? ? "name": "red_bonded",

? ? ? "logistics": "bonded",

? ? ? "customs_code": "SHANGHAI",

? ? ? "is_default": false

? ? }

? ],

? "trade_mode": 0

}

寫(xiě)法:

db.seller.find({ "logistics_infos":{$elemMatch:{name:"red_bonded"}} })

```

### 排序

* 升序

```

db.COLLECTION_NAME.find().sort({KEY:1})

```

* 降序

```

db.COLLECTION_NAME.find().sort({KEY:-1})

```

# MongoDB訪問(wèn)權(quán)限控制

## 訪問(wèn)控制參數(shù)

### **綁定IP地址**

* mongod 啟動(dòng)參數(shù):-bind_ip? <ip_address>?

默認(rèn)值是所有的IP地址都能訪問(wèn),該參數(shù)指定MongoDB對(duì)外提供服務(wù)的綁定IP地址,用于監(jiān)聽(tīng)客戶端 Application的連接,客戶端只能使用綁定的IP地址才能訪問(wèn)mongod,其他IP地址是無(wú)法訪問(wèn)的。

### **設(shè)置監(jiān)聽(tīng)端口**

* mongod 啟動(dòng)參數(shù):-port <port>? ?

MongoDB 默認(rèn)監(jiān)聽(tīng)的端口是27017,該參數(shù)顯式指定MongoDB實(shí)例監(jiān)聽(tīng)的TCP 端口,只有當(dāng)客戶端Application連接的端口和MongoDB實(shí)例監(jiān)聽(tīng)的端口一致時(shí),才能連接到MongoDB實(shí)例。

### **啟用用戶驗(yàn)證**

* mongod 啟動(dòng)參數(shù):-auth?

當(dāng)mongod 使用該參數(shù)啟動(dòng)時(shí),MongoDB會(huì)驗(yàn)證客戶端連接的賬戶和密碼,以確定其是否有訪問(wèn)的權(quán)限。如果認(rèn)證不通過(guò),那么客戶端不能訪問(wèn)MongoDB的數(shù)據(jù)庫(kù)。

### **權(quán)限認(rèn)證**

* mongo 連接參數(shù):-username <username>, -u <username>

* mongo 連接參數(shù):-password <password>, -p <password>

* mongo 連接參數(shù):-authenticationDatabase <dbname> 指定創(chuàng)建User的數(shù)據(jù)庫(kù);在特定的數(shù)據(jù)庫(kù)中創(chuàng)建User,該DB就是User的authentication database。

在連接mongo時(shí),使用參數(shù) --authenticationDatabase,會(huì)認(rèn)證 -u 和 -p 參數(shù)指定的賬戶和密碼。如果沒(méi)有指定驗(yàn)證數(shù)據(jù)庫(kù),mongo使用連接字符串中指定的DB作為驗(yàn)證數(shù)據(jù)塊。

```

mongo 10.4.12.78/admin -u sit-user -p xxxx4qA5 --authenticationDatabase "admin"

```

## **基于角色的訪問(wèn)控制**

**內(nèi)置角色**

內(nèi)置角色是MongoDB預(yù)定義的角色,操作的資源是在DB級(jí)別上。MongoDB擁有一個(gè)SuperUser的角色:root,擁有最大權(quán)限,能夠在系統(tǒng)的所有資源上執(zhí)行任意操作。

* 數(shù)據(jù)庫(kù)內(nèi)置用戶角色

? ? * read:授予User只讀數(shù)據(jù)的權(quán)限

? ? * readWrite:授予User讀寫(xiě)數(shù)據(jù)的權(quán)限

* 數(shù)據(jù)庫(kù)內(nèi)置管理角色

? ? * dbAdmin:在當(dāng)前dB中執(zhí)行管理操作

? ? * dbOwner:在當(dāng)前DB中執(zhí)行任意操作

? ? * userAdmin:在當(dāng)前DB中管理User

* 所有數(shù)據(jù)庫(kù)角色

? ? * readAnyDatabase

? ? * readWriteAnyDatabase

? ? * userAdminAnyDatabase

? ? * dbAdminAnyDatabase

* 超級(jí)用戶角色

? ? * root

### 用戶創(chuàng)建

```

>? db.createUser({user: "jhh",pwd: "pwd",roles: [{role:"readWrite",db:"sms"}]})

Successfully added user: {

? ? "user" : "jhh",

? ? "roles" : [

? ? ? ? {

? ? ? ? ? ? "role" : "readWrite",

? ? ? ? ? ? "db" : "sms"

? ? ? ? }

? ? ]

}

```

> 補(bǔ)充:查看用戶授權(quán)情況可以在admin庫(kù)下通過(guò)db.system.users.find({user:"user_name"})查看。

### **用戶的作用范圍**

在admin 數(shù)據(jù)庫(kù)中創(chuàng)建的角色,作用范圍是全局的,能夠在admin,其他數(shù)據(jù)庫(kù)中使用,并且能夠繼承其他數(shù)據(jù)庫(kù)的角色;而在非admin中創(chuàng)建的角色,作用范圍是當(dāng)前數(shù)據(jù)庫(kù),只能在當(dāng)前DB中使用,只能繼承當(dāng)前數(shù)據(jù)庫(kù)的角色。

# MongoDB備份與恢復(fù)

MongoDB官方提供了兩套數(shù)據(jù)導(dǎo)入導(dǎo)出工具:一般來(lái)說(shuō),進(jìn)行整庫(kù)導(dǎo)出導(dǎo)入時(shí)使用mongodump和mongostore,這一對(duì)組合操作的數(shù)據(jù)是BSON格式,進(jìn)行大量dump和restore時(shí)效率較高。進(jìn)行單個(gè)集合導(dǎo)出導(dǎo)入時(shí)使用mongoexport和mongoimport,這一對(duì)組合操作的數(shù)據(jù)是JSON格式,可讀性較高。


## 數(shù)據(jù)庫(kù)備份與恢復(fù)

* mongodump腳本語(yǔ)法:mongodump -h dbhost -d dbname -o dbdirectory

? ? * -h:

? ? ? ? MongDB所在服務(wù)器地址,例如:127.0.0.1,當(dāng)然也可以指定端口號(hào):127.0.0.1:27017

? ? * -d:

? ? ? ? 需要備份的數(shù)據(jù)庫(kù)實(shí)例,例如:test

? ? * -o**:**

? ? ? ? 備份的數(shù)據(jù)存放位置,例如:\data\dump,當(dāng)然該目錄需要提前建立,在備份完成后,系統(tǒng)自動(dòng)在dump目錄下建立一個(gè)test目錄,這個(gè)目錄里面存放該數(shù)據(jù)庫(kù)實(shí)例的備份數(shù)據(jù)。

* mongorestore腳本語(yǔ)法:mongorestore -h <hostname><:port> -d dbname <path>

? ? * --host <:port>, -h <:port>:

? ? ? ? MongoDB所在服務(wù)器地址,默認(rèn)為: localhost:27017

? ? * --db , -d :

? ? ? ? 需要恢復(fù)的數(shù)據(jù)庫(kù)實(shí)例,例如:test,當(dāng)然這個(gè)名稱也可以和備份時(shí)候的不一樣,比如test2

? ? * --drop:

? ? ? ? 恢復(fù)的時(shí)候,先刪除當(dāng)前數(shù)據(jù),然后恢復(fù)備份的數(shù)據(jù)。

? ? * <path>:

? ? ? ? mongorestore 最后的一個(gè)參數(shù),設(shè)置備份數(shù)據(jù)所在位置,例如:\data\dump\test。

? ? ? ? 你不能同時(shí)指定 <path> 和 --dir 選項(xiàng),--dir也可以設(shè)置備份目錄。

? ? * --dir:

? ? ? ? 指定備份的目錄

? ? ? ? 你不能同時(shí)指定 <path> 和 --dir 選項(xiàng)。

## 集合導(dǎo)入與導(dǎo)出

* mongoexport語(yǔ)法:mongoexport -d dbname -c collectionname -o file --type json/csv -f field

? ? * -h:代表遠(yuǎn)程連接的數(shù)據(jù)庫(kù)地址,默認(rèn)連接本地Mongo數(shù)據(jù)庫(kù)

? ? * --port:代表遠(yuǎn)程連接的數(shù)據(jù)庫(kù)的端口,默認(rèn)連接的遠(yuǎn)程端口27017

? ? * -d :數(shù)據(jù)庫(kù)名

? ? *? -c :collection名

? ? *? -o :輸出的文件名,導(dǎo)出成功后文件會(huì)生成在當(dāng)前執(zhí)行路徑下。

? ? *? --type : 輸出的格式,默認(rèn)為json

? ? *? -f :輸出的字段,如果-type為csv,則需要加上-f "字段名"。

? ? * -q:代表查詢條件

? ? * -limit:讀取指定數(shù)量的數(shù)據(jù)記錄

例:從sit環(huán)境數(shù)據(jù)數(shù)據(jù)庫(kù)導(dǎo)出sms庫(kù)里seller集合任意5文檔到本地。

```

~ ? mongoexport -h=10.4.12.78 -d=sms -c=seller -o=seller.json

--limit=5 -u sit-user -p cDk%KVJA4qA5 --authenticationDatabase=admin --query '{logistics:"auto"}'

2018-07-24T12:50:18.992+0800 connected to: 10.4.12.78

2018-07-24T12:50:19.037+0800 exported 5 records

```

> 注意:這里一定要加—authenticationDatabase=admin指定use和password作為admin庫(kù)的驗(yàn)證,順序直接跟在-u和-p參數(shù)之后,否則會(huì)作為 sms庫(kù)的驗(yàn)證,導(dǎo)致驗(yàn)證失?。ú聹y(cè)sit-user是admin庫(kù)下全局用戶,在sms的庫(kù)用戶中不存在)。具體見(jiàn)“角色作用范圍”一節(jié)。

* mongoimport語(yǔ)法:mongoimport -d dbname -c collectionname --file filename --headerline --type json/csv -f field

? ? *? -d :數(shù)據(jù)庫(kù)名

? ? *? -c :collection名

? ? *? --type :導(dǎo)入的格式默認(rèn)json

? ? *? -f :導(dǎo)入的字段名,type為json格式時(shí)不能指定。

? ? *? --headerline :如果導(dǎo)入的格式是csv,則可以使用第一行的標(biāo)題作為導(dǎo)入的字段

? ? *? --file :要導(dǎo)入的文件

例:將上面導(dǎo)出的seller.json文件導(dǎo)入到本地?cái)?shù)據(jù)庫(kù)sms下。

```

~ ? mongoimport -d sms? -c seller --file seller.json --type json

2018-07-24T13:39:05.380+0800? ? connected to: localhost

2018-07-24T13:39:05.394+0800? ? imported 5 documents

```

客戶端查看seller集合文檔條數(shù):

```

導(dǎo)入執(zhí)行前:

> db.seller.find().count();

2

導(dǎo)入執(zhí)行后:

> db.seller.find().count();

7

```

# 數(shù)據(jù)庫(kù)與緩存之間更新機(jī)制

## **緩存同步的常用模式**

緩存同步的模式,可以按照緩存的用途(主要用于讀或者寫(xiě))分為兩類(lèi):讀緩存的同步和寫(xiě)緩存的同步。

讀緩存的同步:

### **緩存預(yù)加載模式**

提前將數(shù)據(jù)從數(shù)據(jù)庫(kù)加載到緩存,如果數(shù)據(jù)庫(kù)有寫(xiě)更新,同步更新緩存。

### **緩存直讀模式**

應(yīng)用先查看緩存中是否有該數(shù)據(jù),有則直接使用,如果沒(méi)有,從數(shù)據(jù)庫(kù)加載,然后放入緩存,下次以后再訪問(wèn)就可以直接從緩存中獲得。

### **緩存直寫(xiě)模式**

在數(shù)據(jù)更新時(shí),同時(shí)寫(xiě)入緩存和數(shù)據(jù)庫(kù)。這種模式是最穩(wěn)妥的辦法,但是性能會(huì)受到一定的影響。

其中的過(guò)程是這樣的:

1.檢查用戶請(qǐng)求的數(shù)據(jù)是緩存中是否有存在,如果有存在的話,只需要直接把請(qǐng)求的數(shù)據(jù)返回,無(wú)需查詢數(shù)據(jù)庫(kù)。

2.如果請(qǐng)求的數(shù)據(jù)在緩存中找不到,這時(shí)候再去查詢數(shù)據(jù)庫(kù)。返回請(qǐng)求數(shù)據(jù)的同時(shí),把數(shù)據(jù)存儲(chǔ)到緩存中一份。

3.保持緩存的“新鮮性”,每當(dāng)數(shù)據(jù)發(fā)生變化的時(shí)候(比如,數(shù)據(jù)有被修改,或被刪除的情況下),要同步的更新緩存信息,確保用戶不會(huì)在緩存取到舊的數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 數(shù)據(jù)庫(kù)的基本操作 use db_name 創(chuàng)建數(shù)據(jù)庫(kù) db 查看當(dāng)前連接的數(shù)據(jù)庫(kù) show dbs 顯示所有數(shù)據(jù)庫(kù)...
    alonwang閱讀 881評(píng)論 0 1
  • MongoDB常用操作 一、增刪改查 查看當(dāng)前數(shù)據(jù)庫(kù)中所有的集合,使用命令 創(chuàng)建集合有兩種方式,顯示創(chuàng)建和隱式創(chuàng)建...
    我可能是個(gè)假開(kāi)發(fā)閱讀 1,098評(píng)論 4 12
  • 一、數(shù)據(jù)庫(kù)常用命令1、Help查看命令提示 2、切換/創(chuàng)建數(shù)據(jù)庫(kù) 當(dāng)創(chuàng)建一個(gè)集合(table)的時(shí)候會(huì)自動(dòng)創(chuàng)建當(dāng)前...
    十九樓的清風(fēng)閱讀 520評(píng)論 0 0
  • 一、MongoDB簡(jiǎn)介 1.概述 ? MongoDB是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫(kù),由C++語(yǔ)言編寫(xiě)。旨在為WE...
    鄭元吉閱讀 1,130評(píng)論 0 2
  • 周衛(wèi)平焦點(diǎn)網(wǎng)絡(luò)第十期堅(jiān)持分享第214天 當(dāng)事人之所以會(huì)前來(lái)晤談,常是因?yàn)樗麄兿M约骸案谩?;“更好”可能是想去?..
    心所安處閱讀 131評(píng)論 0 0

友情鏈接更多精彩內(nèi)容