# MongoDB
## 數據庫分類
### 關系型數據庫
* 具備ACID特性
? ? * Atomic原子性,也就是說事務里的所有操作要么全部做完,要么都不做,事務成功的條件是事務里的所有操作都成功,只要有一個操作失敗,整個事務就失敗,需要回滾。*比如銀行轉賬,從A賬戶轉100元至B賬戶,分為兩個步驟:1)從A賬戶取100元;2)存入100元至B賬戶。這兩步要么一起完成,要么一起不完成,如果只完成第一步,第二步失敗,錢會莫名其妙少了100元。*
? ? * Consistency一致性,也就是說數據庫要一直處于一致的狀態,事務的運行不會改變數據庫原本的一致性約束。*例如現有完整性約束a+b=10,如果一個事務改變了a,那么必須得改變b,使得事務結束后依然滿足a+b=10,否則事務*失敗。
? ? * Isolation獨立性,所謂的獨立性是指并發的事務之間不會互相影響,如果一個事務要訪問的數據正在被另外一個事務修改,只要另外一個事務未提交,它所訪問的數據就不受未提交事務的影響。*比如現在有個交易是從A賬戶轉100元至B賬戶,在這個交易還未完成的情況下,如果此時B查詢自己的賬戶,是看不到新增加的100元的。*
? ? * Durability持久性,持久性是指一旦事務提交后,它所做的修改將會永久的保存在數據庫上,即使出現宕機也不會丟失。
* 局限性和不適用場景
? ? * 關系型數據庫為了維護一致性所付出的巨大代價就是其讀寫性能比較差。在網頁應用中,尤其是SNS(社交)應用中,一致性卻不是顯得那么重要,用戶A看到的內容和用戶B看到同一用戶C內容更新不一致是可以容忍的,或者說,兩個人看到同一好友的數據更新的時間差那么幾秒是可以容忍的,因此,關系型數據庫的最大特點在這里已經無用武之地,起碼不是那么重要了。
? ? * 關系數據庫的另一個特點就是其具有固定的表結構,因此,其擴展性比較差,而在SNS中,系統的升級,功能的增加,往往意味著數據結構巨大變動,這一點關系型數據庫也難以應付,需要新的結構化數據存儲。
### **非關系型數據庫 NoSQL(Not Only SQL )**
*? NoSQL數據庫的四大分類
|分類 |舉例 |典型應用場景 |數據模型 |優點 |缺點 |
|--- |--- |--- |--- |--- |--- |
|鍵值(key-value)存儲數據庫 |Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB |內容緩存,主要用于處理大量數據的高訪問負載,也用于一些日志系統等等。 |Key 指向 Value 的鍵值對,通常用hash table來實現 |查找速度快 |數據無結構化,通常只被當作字符串或者二進制數據 |
|--- |--- |--- |--- |--- |--- |
|**列存儲數據庫** |Cassandra, HBase, Riak |分布式的文件系統 |以列簇式存儲,將同一列數據存在一起 |查找速度快,可擴展性強,更容易進行分布式擴展 |功能相對局限 |
|**文檔型數據庫** |CouchDB, MongoDb |Web應用(與Key-Value類似,Value是結構化的,不同的是數據庫能夠了解Value的內容) |Key-Value對應的鍵值對,Value為結構化數據 |數據結構要求不嚴格,表結構可變,不需要像關系型數據庫一樣需要預先定義表結構 |查詢性能不高,而且缺乏統一的查詢語法。 |
|**圖形(Graph)數據庫** |Neo4J, InfoGrid, Infinite Graph |社交網絡,推薦系統等。專注于構建關系圖譜 |圖結構 |利用圖結構相關算法。比如最短路徑尋址,N度關系查找等 |很多時候需要對整個圖做計算才能得出需要的信息,而且這種結構不太好做分布式的集群方案。 |
* Mongodb
? ? * 是文檔型的非關系型數據庫,使用bson( Binary Serialized Document Format) 結構。其優勢在于查詢功能比較強大,能存儲海量數據。
# Mac OSX 平臺安裝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
```
## 運行mongoDB服務
1、首先創建一個數據庫存儲目錄 /data/db,命令行輸入:sudo mkdir -p /data/db
2、創建日志文件:sudo vim /data/db/mongo.log;創建pid文件:sudo vim /var/run/mongo.pid
3、啟動 mongodb,分兩種啟動方式:
* 啟動命令直接指定命令參數方式:sudo mongod -port 27017 -dbpath /data/db -fork? -pidfilepath=/var/run/mongo.pid? -logpath /data/db/mongo.log
* 啟動命令指定配置文件方式:
? ? * 1、創建配置文件 :sudo vim /etc/mongodb.conf?
? ? *? ? 2、執行:sudo mongo -f /etc/mongodb.conf
* 啟動參數說明(可以通過mongo -help來查看全部參數):
? ? * -port arg? ? #指定服務端口號,默認端口27017。
? ? * -dbpath? ? #? 指定存儲路徑。
? ? * -logpath arg? ? # 指定MongoDB日志文件,注意是指定文件不是目錄。使用fork參數時因為日志無法寫到控制臺,所以需要同時使用logpath參數。
? ? * -pidfilepath arg? ? # 指定PID File 的完整路徑,如果沒有設置,則沒有PID文件。
? ? * -fork? ? # 以守護進程的方式運行MongoDB,相當于nohup “shell”? &用法。使用fork參數時因為日志無法寫到控制臺,所以需要同時使用logpath參數。
? ? * -directoryperdb? ? # 設置每個數據庫將被保存在一個單獨的目錄
? ? * -maxConns arg? # 最大同時連接數 默認2000
? ? * -auth? ? #用戶認證,默認false,當設置為true時候,進入數據庫需要auth驗證,當數據庫里沒有用戶,則不需要驗證也可以操作。直到創建了第一個用戶,之后操作都需要驗證。
啟動成功后可以看到以下提示:
```
[initandlisten] waiting for connections on port 27017
或
forked process: 41540
child process started successfully, parent exiting
```
## 停止mongoDB服務
正常關閉方式:
* 前臺方式啟動時,命令行光標鍵入CTRL+C
* 通過連接的客戶端關閉,首先連接mongo成功后
? ? * 第一步:use admin
? ? * 第二步:db.shutdownServer()
異常關閉再次啟動報錯時:
* 使用kill進程方式
? ? * ps -ef |grep mongo
? ? * kill -15 pid? ? #建議不要使用 ”kill -9 pid“,因為如果運行在沒開啟日志(—journal)的情況下,可能會造成數據損失。
> 注意:在mongodb的啟動時,在數據目錄下,會生成一個mongod.lock文件。如果在正常退出時,會清除這個mongod.lock文件,若是異常退出,在下次啟動的時候,會禁止啟動,并看到下面的報錯。
```
? ? 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連接
### 客戶端連接
語法格式:mongo 遠程主機ip或DNS:端口號/數據庫名 -u user -p password
例:連接本地數據庫,在終端窗口輸入:mongo
```
~ ? mongo
MongoDB shell version v4.0.0
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 4.0.0
```
例:連接遠程sit環境mongo數據庫
```
~ ? 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
```
### 標準uri連接
語法格式: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語法
## 概念術語
|SQL術語/概念 |MongoDB術語/概念 |解釋/說明 |
|--- |--- |--- |
|database |database |數據庫 |
|--- |--- |--- |
|table |collection |數據庫表/集合 |
|row |document |數據記錄行/文檔 |
|column |field |數據字段 |
|index |index |索引 |
|primary key |primary key |主鍵,MongoDB自動將_id字段設置為主鍵 |
## 數據庫操作
### 創建數據庫
1、語法格式:use <database_name>? ? #如果數據庫存在時會切換到該數據庫,不存在時會創建該數據庫。
2、操作成功后可以看到提示:
```
> use sms
switched to db sms
```
### 刪除數據庫
1、語法格式:db.dropDatabase()? ? #刪除當前使用的數據庫,可以通過命令“db”來查看當前數據庫
2、操作成功后可以看到提示:
```
> db? ? #查看當前數據庫
sms
> db.dropDatabase()
{ "ok" : 1 }
```
## 集合操作
### 創建集合
1、語法格式:db.createCollection(<name>,{ <options>})? ? #name為要創建的集合名,options為可選參數:
* capped? ? #布爾類型,如果為 true,則創建固定集合。固定集合是指有著固定大小的集合,當達到最大值時,它會自動覆蓋最早的文檔。當該值為 true 時,必須指定 size 參數。
* size? ? #數值,為固定集合指定一個最大值(以字節計)。如果 capped 為 true,也需要指定該字段**。**
* max? ? #數值,指定固定集合中包含文檔的最大數量。
2、執行:db.createCollection("seller",{ capped : true, size :6142800, max : 10000 },創建集合成功后可以看到提示:
```
> db? ? #查看當前數據庫
sms
> db.createCollection("seller",{ capped : true, size :6142800, max : 10000 })
{ "ok" : 1 }
```
### 刪除集合
1、語法格式:db.collection_name.drop()
2、刪除集合成功后,可以看到命令行返回“true”,否則返回“false”。
```
> show collections? ? #查看當前數據庫下的集合
ark_open_api_account
seller
> db.ark_open_api_account.drop()
true
> show collections
seller
```
## 文檔操作
### 創建文檔
1、語法格式:db.collection_name.insert(<document>)
2、執行db.seller.insert({"role" : "partner","shopname" : "redqa009-測試","email" : "[xx@163.com](mailto:xx@163.com)"})?
```
> db.seller.insert({"role" : "partner","shopname" : "redqa009-測試","email" : "[xx@163.com](mailto:xx@163.com)"})
WriteResult({ "nInserted" : 1 })
> db.seller.find()? ? #查詢文檔
{ "_id" : ObjectId("5b554bd275f30ccd39ca6483"), "role" : "partner", "shopname" : "redqa009-測試", "email" : "xx@163.com" }
```
或? 先定義document后再執行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-測試", "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、語法格式:
```
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,? # 可選,含義為如果不存在update的記錄,是否插入objNew,true為插入,默認是false,不插入。
multi: <boolean>,? # 可選,默認是false,只更新找到的第一條記錄,如果這個參數為true,就把按條件查出來多條記錄全部更新。
writeConcern: <document>? # writeConcern** **:可選,拋出異常的級別。
}
)
```
? ? * 2、更新shopname為"redqa009-測試1”商家的郵箱
? ? * 執行'db.seller.update({shopname:"redqa009-測試1"},{$set:{email:"xx@163.com"}},{upsert:true})'
```
> db.seller.find()
{ "_id" : ObjectId("5b554bd275f30ccd39ca6483"), "role" : "partner", "shopname" : "redqa009-測試", "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-測試1"},{$set:{email:"xx@163.com"}},{upsert:true})
WriteResult({
? ? "nMatched" : 0,
? ? "nUpserted" : 1,
? ? "nModified" : 0,
? ? "_id" : ObjectId("5b556dca30563a38f0284e00")
})
```
> 注意:當集合為Capped collection時,如果更新或替換操作更改了文檔大小,則操作將失敗。錯誤提示如下:
```
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、語法格式
```
db.collection.save(
? <document>,? ? # 根據文檔中的'_id'字段,找到一個已經存在的文檔,進行更新。
? {
? ? writeConcern: <document>
? }
)
```
> 補充:
> 當文檔中包含'_id'字段,但匹配不到已存在的文檔,也會將文檔插入數據庫。
> 當文檔中不含'_id'字段,save方法將調用insert方法,插入這條文檔并分配一個_id。
### 刪除文檔
1、語法格式:
```
db.collection.remove(
? <query>,? ? # 可選,刪除的文檔的條件。
? {
? ? justOne: <boolean>,? ? # 可選,如果設為 true 或 1,則只刪除一個文檔。
? ? writeConcern: <document>
? }
)
```
> 注意:Capped collection不允許使用remove()方法刪除,只能使用db.collection.drop()方法刪除集合。db.collection.isCapped() 命令可以查看一個集合是否是 Capped Collection。
### 查詢文檔
```
1、db.collection.find(query, projection) # 可選,query為查詢條件,可選,projection指定返回的鍵。
```
### 比較操作符
* 大于:$gt
* 大于等于:$gte
* 小于:$lt
* 小于等于:$lte
* 等于:$eq
例:查詢訂單“total_discounted_price”大于等于100并且小于等于200的任意一個訂單號。
```
db.order.findOne({total_discounted_price:{$gte:150,$lte:200}},{order_id:1})
#projection:1代表只返回指定字段,為0代表不返回該字段。
```
* 不等于:$ne
例:查詢商家("seller":"53df5710b4c4d6383ae8e9a6")任意一個不是“已取消”的訂單
```
db.order_package.find({"seller":"53df5710b4c4d6383ae8e9a6","status":{$ne:998}})
```
* 匹配數組中任意值:$in
例:查詢所有訂單狀態狀態為“待配貨”、“配貨中”或“已發貨”的訂單。
```
db.order_package.find({ "status": {$in:[4,5,6]}})
```
* 不匹配數組中任意值:$nin
### 邏輯操作符
* 與查詢:$and
例:查詢商家("seller":"53df5710b4c4d6383ae8e9a6")所有訂單狀態狀態為“待配貨”、“配貨中”或“已發貨”的訂單。
```
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的訂單號。
```
db.order.find({$or:[{total_discounted_price:{$lte:100}},{total_discounted_price:{$gte:200}}]})
```
### 元素操作符
* 查詢是否存在某字段:$exists
例:查詢維護了貿易模式的所有商家。
```
db.seller.find({ "trade_mode":{$exists:true} })
```
*? 查詢數組中元素是否滿足指定的條件:$elemMatch
例:查詢所有支持“red_bonded”物流模式的商家。
```
被查詢集合的數據結構:
{
? "_id": ObjectId("5a151d9deb90b912e76ee832"),
? "shopname": "redqa009-測試",
? "logistics_infos": [
? ? {
? ? ? "name": "red_auto",
? ? ? "logistics": "auto",
? ? ? "is_default": true
? ? },
? ? {
? ? ? "name": "red_bonded",
? ? ? "logistics": "bonded",
? ? ? "customs_code": "SHANGHAI",
? ? ? "is_default": false
? ? }
? ],
? "trade_mode": 0
}
寫法:
db.seller.find({ "logistics_infos":{$elemMatch:{name:"red_bonded"}} })
```
### 排序
* 升序
```
db.COLLECTION_NAME.find().sort({KEY:1})
```
* 降序
```
db.COLLECTION_NAME.find().sort({KEY:-1})
```
# MongoDB訪問權限控制
## 訪問控制參數
### **綁定IP地址**
* mongod 啟動參數:-bind_ip? <ip_address>?
默認值是所有的IP地址都能訪問,該參數指定MongoDB對外提供服務的綁定IP地址,用于監聽客戶端 Application的連接,客戶端只能使用綁定的IP地址才能訪問mongod,其他IP地址是無法訪問的。
### **設置監聽端口**
* mongod 啟動參數:-port <port>? ?
MongoDB 默認監聽的端口是27017,該參數顯式指定MongoDB實例監聽的TCP 端口,只有當客戶端Application連接的端口和MongoDB實例監聽的端口一致時,才能連接到MongoDB實例。
### **啟用用戶驗證**
* mongod 啟動參數:-auth?
當mongod 使用該參數啟動時,MongoDB會驗證客戶端連接的賬戶和密碼,以確定其是否有訪問的權限。如果認證不通過,那么客戶端不能訪問MongoDB的數據庫。
### **權限認證**
* mongo 連接參數:-username <username>, -u <username>
* mongo 連接參數:-password <password>, -p <password>
* mongo 連接參數:-authenticationDatabase <dbname> 指定創建User的數據庫;在特定的數據庫中創建User,該DB就是User的authentication database。
在連接mongo時,使用參數 --authenticationDatabase,會認證 -u 和 -p 參數指定的賬戶和密碼。如果沒有指定驗證數據庫,mongo使用連接字符串中指定的DB作為驗證數據塊。
```
mongo 10.4.12.78/admin -u sit-user -p xxxx4qA5 --authenticationDatabase "admin"
```
## **基于角色的訪問控制**
**內置角色**
內置角色是MongoDB預定義的角色,操作的資源是在DB級別上。MongoDB擁有一個SuperUser的角色:root,擁有最大權限,能夠在系統的所有資源上執行任意操作。
* 數據庫內置用戶角色
? ? * read:授予User只讀數據的權限
? ? * readWrite:授予User讀寫數據的權限
* 數據庫內置管理角色
? ? * dbAdmin:在當前dB中執行管理操作
? ? * dbOwner:在當前DB中執行任意操作
? ? * userAdmin:在當前DB中管理User
* 所有數據庫角色
? ? * readAnyDatabase
? ? * readWriteAnyDatabase
? ? * userAdminAnyDatabase
? ? * dbAdminAnyDatabase
* 超級用戶角色
? ? * root
### 用戶創建
```
>? db.createUser({user: "jhh",pwd: "pwd",roles: [{role:"readWrite",db:"sms"}]})
Successfully added user: {
? ? "user" : "jhh",
? ? "roles" : [
? ? ? ? {
? ? ? ? ? ? "role" : "readWrite",
? ? ? ? ? ? "db" : "sms"
? ? ? ? }
? ? ]
}
```
> 補充:查看用戶授權情況可以在admin庫下通過db.system.users.find({user:"user_name"})查看。
### **用戶的作用范圍**
在admin 數據庫中創建的角色,作用范圍是全局的,能夠在admin,其他數據庫中使用,并且能夠繼承其他數據庫的角色;而在非admin中創建的角色,作用范圍是當前數據庫,只能在當前DB中使用,只能繼承當前數據庫的角色。
# MongoDB備份與恢復
MongoDB官方提供了兩套數據導入導出工具:一般來說,進行整庫導出導入時使用mongodump和mongostore,這一對組合操作的數據是BSON格式,進行大量dump和restore時效率較高。進行單個集合導出導入時使用mongoexport和mongoimport,這一對組合操作的數據是JSON格式,可讀性較高。
## 數據庫備份與恢復
* mongodump腳本語法:mongodump -h dbhost -d dbname -o dbdirectory
? ? * -h:
? ? ? ? MongDB所在服務器地址,例如:127.0.0.1,當然也可以指定端口號:127.0.0.1:27017
? ? * -d:
? ? ? ? 需要備份的數據庫實例,例如:test
? ? * -o**:**
? ? ? ? 備份的數據存放位置,例如:\data\dump,當然該目錄需要提前建立,在備份完成后,系統自動在dump目錄下建立一個test目錄,這個目錄里面存放該數據庫實例的備份數據。
* mongorestore腳本語法:mongorestore -h <hostname><:port> -d dbname <path>
? ? * --host <:port>, -h <:port>:
? ? ? ? MongoDB所在服務器地址,默認為: localhost:27017
? ? * --db , -d :
? ? ? ? 需要恢復的數據庫實例,例如:test,當然這個名稱也可以和備份時候的不一樣,比如test2
? ? * --drop:
? ? ? ? 恢復的時候,先刪除當前數據,然后恢復備份的數據。
? ? * <path>:
? ? ? ? mongorestore 最后的一個參數,設置備份數據所在位置,例如:\data\dump\test。
? ? ? ? 你不能同時指定 <path> 和 --dir 選項,--dir也可以設置備份目錄。
? ? * --dir:
? ? ? ? 指定備份的目錄
? ? ? ? 你不能同時指定 <path> 和 --dir 選項。
## 集合導入與導出
* mongoexport語法:mongoexport -d dbname -c collectionname -o file --type json/csv -f field
? ? * -h:代表遠程連接的數據庫地址,默認連接本地Mongo數據庫
? ? * --port:代表遠程連接的數據庫的端口,默認連接的遠程端口27017
? ? * -d :數據庫名
? ? *? -c :collection名
? ? *? -o :輸出的文件名,導出成功后文件會生成在當前執行路徑下。
? ? *? --type : 輸出的格式,默認為json
? ? *? -f :輸出的字段,如果-type為csv,則需要加上-f "字段名"。
? ? * -q:代表查詢條件
? ? * -limit:讀取指定數量的數據記錄
例:從sit環境數據數據庫導出sms庫里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庫的驗證,順序直接跟在-u和-p參數之后,否則會作為 sms庫的驗證,導致驗證失?。ú聹ysit-user是admin庫下全局用戶,在sms的庫用戶中不存在)。具體見“角色作用范圍”一節。
* mongoimport語法:mongoimport -d dbname -c collectionname --file filename --headerline --type json/csv -f field
? ? *? -d :數據庫名
? ? *? -c :collection名
? ? *? --type :導入的格式默認json
? ? *? -f :導入的字段名,type為json格式時不能指定。
? ? *? --headerline :如果導入的格式是csv,則可以使用第一行的標題作為導入的字段
? ? *? --file :要導入的文件
例:將上面導出的seller.json文件導入到本地數據庫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集合文檔條數:
```
導入執行前:
> db.seller.find().count();
2
導入執行后:
> db.seller.find().count();
7
```
# 數據庫與緩存之間更新機制
## **緩存同步的常用模式**
緩存同步的模式,可以按照緩存的用途(主要用于讀或者寫)分為兩類:讀緩存的同步和寫緩存的同步。
讀緩存的同步:
### **緩存預加載模式**
提前將數據從數據庫加載到緩存,如果數據庫有寫更新,同步更新緩存。
### **緩存直讀模式**
應用先查看緩存中是否有該數據,有則直接使用,如果沒有,從數據庫加載,然后放入緩存,下次以后再訪問就可以直接從緩存中獲得。
### **緩存直寫模式**
在數據更新時,同時寫入緩存和數據庫。這種模式是最穩妥的辦法,但是性能會受到一定的影響。
其中的過程是這樣的:
1.檢查用戶請求的數據是緩存中是否有存在,如果有存在的話,只需要直接把請求的數據返回,無需查詢數據庫。
2.如果請求的數據在緩存中找不到,這時候再去查詢數據庫。返回請求數據的同時,把數據存儲到緩存中一份。
3.保持緩存的“新鮮性”,每當數據發生變化的時候(比如,數據有被修改,或被刪除的情況下),要同步的更新緩存信息,確保用戶不會在緩存取到舊的數據。