[TOC]
## 通過配置文件啟動mongo服務器
| 參數 |含義 |
| --- | --- |
|--dbpath | 指定數據庫文件存放的目錄|
|--port | 端口默認是27017 |
|--fork | 以后臺守護的方式進行啟動 |
|--logpath | 指定日志文件輸出路徑|
|--config | 指定一個配置文件 |
|--auth | 以安全方式啟動數據庫,需要驗證賬號和密碼|
直接在命令行中通過`mongod --dbpath ...`這樣啟動服務器,如果參數太多的話,就比較麻煩
So,我們可以選擇通過運行配置文件的方式啟動服務器
首先,要在一個目錄下創建一個`mongo.config`(后綴名無所謂)
>[warning] **注意:** log文件會自動生成,但data目錄必須優先創建好
```
//mongo.config文件
dbpath=E:\mongouse\data
#數據庫日志存放目錄
logpath=E:\mongouse\log
#以追加的方式記錄日志
logappend = true
#端口號 默認為27017
port=27017
#以后臺方式運行進程
fork=true
#開啟用戶認證
auth=false
#關閉http接口,默認關閉http端口訪問
nohttpinterface=true
#mongodb所綁定的ip地址
bind_ip = 127.0.0.1
#啟用日志文件,默認啟用
journal=true
#這個選項可以過濾掉一些無用的日志信息,若需要調試使用請設置為false
quiet=true
```
然后在命令行中輸入
```
mongod --config mongo.config
```
## 導入導出數據
- mongoimport 導入
- mongoexport 導出
| 參數 |含義 |
| --- | --- |
| -h[--host] |鏈接的數據庫 |
| --port | 端口號|
| -u| 用戶名|
|-p | 密碼|
|-d | 指定哪個數據庫|
|-c | 指定導出的集合|
|-o | 導出的路徑|
|-q | 進行過濾的|
### 方法一
#### mongoexport與導出數據庫
```
mongoexport -d school -c students -o ./stu.bak
```
導出的是一個文件

整個文件是一個json

#### mongoimport與導入數據庫
```
mongoimport -h 127.0.0.1 --port 27017 -d school -c students --file stu.bak
```
默認`-h`、`-p`、`--file`都可以省略
### 方法二
#### mongodump與導出數據庫
和上面的區別在于不會轉換(上面的會轉換成json),適用于數據庫中存在二進制數據的情況(二進制是轉換不成json的)
導出整個數據庫
```
mongodump -o mdmp
```
導出其中一個數據庫
```
mongodump -d school -o school.dmp
```
導出來的樣子

(school.dmp文件夾下有一個school文件)
#### mongorestore與導入數據庫
如果想要導入整個數據庫
```
mongorestore mdmp
```
如果只想導入其中一個數據庫
```
mongorestore -d school mdmp/school
```
### 方法三:直接拷貝數據
將整個文件夾拷貝到指定目錄下,然后在啟動數據庫服務器時將其指定為`--dbpath`
## 鎖定和解鎖數據庫
>強制將緩存區中的數據真正寫入后鎖住數據庫
必須在admin數據庫中使用命令
```
db.runCommand({fsync:1,lock:1}); //類似于node中的fs.fsync
```
>解鎖
```
db.fsyncUnlock();
```
示例:
打開一個命令行,先鎖住

再打開一個命令行,像數據庫中寫入,會發現

遲遲不返回,說明正在等待寫入
但當我們解鎖

會發現原本正在等待的數據已經寫入

## 安全措施
- 物理隔離:電都不插
- 網絡隔離:區域網
- 防火墻(IP/IP段/白名單/黑名單)
- 用戶名和密碼驗證
## 用戶管理
要使用戶生效,需要在啟動服務器時加上`--auth`
```
mongod ... --auth
```
這樣我們就不能裸連數據庫了,必須要使用賬號登錄。
### 查看角色
```
show roles;
```
內置角色
- 數據庫用戶角色:read、readWrite;
- 數據庫管理角色:dbAdmin、dbOwner、userAdmin
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManage;
- 備份恢復角色:backup、restore
- 所有數據庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
- 超級用戶角色:root
- 內部角色:_system
用戶的操作都需要在admin下面進行操作
如果在某個數據庫下面執行操作,那么只對當前數據庫生效
addUser已經廢棄,默認會創建root用戶,不安全,不再建議使用
### 創建用戶
針對school數據庫可以讀
```
db.createUser({user:'ahhh',pwd:'123',roles:[{db:'school',role:'read'}]});
```
`roles`中不加db表示對所有數據庫都有權限
### 顯示用戶權限
```
use admin;
var r = db.runCommand({usersInfo:'ahhh',showPrivileges:true})
printjson(r);
```
### 修改密碼
修改密碼
```
db.changeUserPassword({'ahhh','123456'});
```
驗證密碼是否正確
```
db.auth('ahhh','123456')
```
### 添加個人信息
```
db.runCommand({updateUser:'ahhh',pwd:'123',customData:{name:'ahuang',age:111,telephone:'123123xxx'}});
```
## 高級命令
首先`runCommand`中的參數是一個文檔(JSON),但在runCommand中它是具有特殊意義的一些字段。
### load('')
路徑分隔符必須使用`/`而不是`\`
```
D:\WEB\database\data //-->錯誤的
D:/WEB/database/data //-->正確的
```
### group:分組
有以下數據
```
var stus = [
{province:'北京',home:'北京',age:1}
,{province:'北京',home:'北京',age:2}
,{province:'北京',home:'北京',age:3}
,{province:'廣東',home:'廣州',age:1}
,{province:'廣東',home:'佛山',age:2}
,{province:'廣東',home:'東莞',age:3}
]
```
我們這樣執行命令進行分組
```
db.runCommand({
group:{
ns:'students' //namespace
,key:{home:1} //按照哪個key分組 可以寫很多個
,query:{age:{$gt:1}} //滿足條件才參與分組
,initial:{total:0} //每一組的初始值
,$reduce:function(doc,initial){
initial.total += doc.age; //每個文檔累加一次 最終會得到該分組下所有年齡的總和
}
}
});
```
分組結果
```
//retval:返回值類型說明
{
"retval" : [
{
"home" : "北京",
"total" : 5
},
{
"home" : "佛山",
"total" : 2
},
{
"home" : "東莞",
"total" : 3
}
],
"count" : NumberLong(4),
"keys" : NumberLong(3),
"ok" : 1
}
```
### distinct:查找不重復的key值
以下會在students集合下查找所有key為home的值
```
db.runCommand({distinct:'students',key:'home'});
```
返回是這樣的
```
{ "values" : [ "北京", "廣州", "佛山", "東莞" ], "ok" : 1 }
```
執行命令時也可以這樣執行
```
db.runCommand({distinct:'students',key:'home'}).values;
```
這樣能直接得到key的值組成的數組
```
[ "北京", "廣州", "佛山", "東莞" ]
```
### drop
刪除集合除了`db.xxx.drop()`,也可以
```
db.runCommand({drop:'students'});
```
### 其它
查看數據庫信息
```
db.runCommand({buildInfo:1});
```
查看students集合下上一次的執行錯誤信息
```
db.runCommand({getLastError:'students'});
```
## 固定集合
有著固定大小的集合,滿了以后會覆蓋掉最先插入的。(先入先出)
### 特性
- 沒有索引
- 插入和查詢速度非常快,不需要重新分配空間
- 特別適合存儲日志
### 創建固定集合

- size單位是**kb**
- max單位是**個**
- capped:是否有上限封頂,必須為true
```
db.createCollection('logs',{size:5,max:5,capped:true})
```
### 非固定集合轉換為固定集合
```
db.runCommand({convertToCapped:'logs',size:5})
```
## gridfs:網格文件存儲系統
gridfs是mongodb自帶的文件系統,使用二進制存儲文件。
mongodb可以以BSON格式保存二進制對象,但是BSON對象的體積不能超過4M。所以mongodb提供了`mongofiles`。它可以把一個大文件透明地分割成小文件(256k),從而保存大體積的數據
GridFS用于存儲和恢復那些超過16M(BSON文件限制)的文件(如:圖片、音頻、視頻等)
GridFS用兩個集合來存儲一個文件:fs.files(元信息)與fs.chunks(實際內容)
每個文件的實際內容被存在chunks(二進制數據)中,和文件有關的meta數據(filename,content_type,還有用戶自定義的屬性)將會被存在files集合中。
### 使用
#### 存儲
將1.txt放到myfiles數據庫中
```
mongofiles -d myfiles put 1.txt
```
一個文件會在`fs.files`中對應一個id
假如我們有兩份文件存儲在gridfs中

可以發現files中有兩個id
但`fs.chunks`中則不是這樣了,它會分成很多份

#### 查看文件列表
查看myfiles數據庫下的所有文件
```
mongofiles -d myfiles list
```
#### 詳細查看文件信息
```
db.fs.files.find();
db.fs.files.find(files_id:objectId(''));;
```
#### 獲取&&下載
```
mongofiles -d myfile get 1.txt
```
#### 刪除文件
```
mongofiles -d myfiles delete 1.txt
```
## eval
執行腳本
```
db.eval('1+1');
<<<
2
```
```
db.eval("return 'hello'");
<<<
hello
```
```
db.system.js.insert({_id:'xx',value:'111'});
//類似于聲明了一個全局變量
db.eval("return xx");
<<<
111
```
會存儲在當前數據庫下的`Functions`文件夾下(和Collections文件夾同級)

```
db.system.js.insert({_id:'say',value:function(){return 'hello'}});
//類似于聲明了一個全局變量
db.eval("say()");
<<<
hello
```
