[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
```
导出的是一个文件
![](https://box.kancloud.cn/ae43daa34cc45cfd34c582e1ac6aa2ad_592x32.png)
整个文件是一个json
![](https://box.kancloud.cn/e0ab8c1f75ee43b1128e9b5dc04db926_635x80.png)
#### 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
```
导出来的样子
![](https://box.kancloud.cn/80c6ab1e477b5426d386243942a50886_493x100.png)
(school.dmp文件夹下有一个school文件)
#### mongorestore与导入数据库
如果想要导入整个数据库
```
mongorestore mdmp
```
如果只想导入其中一个数据库
```
mongorestore -d school mdmp/school
```
### 方法三:直接拷贝数据
将整个文件夹拷贝到指定目录下,然后在启动数据库服务器时将其指定为`--dbpath`
## 锁定和解锁数据库
>强制将缓存区中的数据真正写入后锁住数据库
必须在admin数据库中使用命令
```
db.runCommand({fsync:1,lock:1}); //类似于node中的fs.fsync
```
>解锁
```
db.fsyncUnlock();
```
示例:
打开一个命令行,先锁住
![](https://box.kancloud.cn/067d3b81b1da8107181d6c17ba54330a_630x98.png)
再打开一个命令行,像数据库中写入,会发现
![](https://box.kancloud.cn/fa790aafb03078da42b6ab4bd08d6a1a_288x70.png)
迟迟不返回,说明正在等待写入
但当我们解锁
![](https://box.kancloud.cn/f4520d96008f08a8428f3b64e6d21d65_621x43.png)
会发现原本正在等待的数据已经写入
![](https://box.kancloud.cn/1640339c4d1e3de2a5ccedf4209d9b63_291x36.png)
## 安全措施
- 物理隔离:电都不插
- 网络隔离:区域网
- 防火墙(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'});
```
## 固定集合
有着固定大小的集合,满了以后会覆盖掉最先插入的。(先入先出)
### 特性
- 没有索引
- 插入和查询速度非常快,不需要重新分配空间
- 特别适合存储日志
### 创建固定集合
![](http://img.zhufengpeixun.cn/firstinfirstout.png)
- 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中
![](https://box.kancloud.cn/eb3ccc1854805a18e143bc64b1e1da5b_751x94.png)
可以发现files中有两个id
但`fs.chunks`中则不是这样了,它会分成很多份
![](https://box.kancloud.cn/044661605ba33925376b07df492f1c1f_600x240.png)
#### 查看文件列表
查看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文件夹同级)
![](https://box.kancloud.cn/e146da5d4bbb0171548f894a951a3631_371x173.png)
```
db.system.js.insert({_id:'say',value:function(){return 'hello'}});
//类似于声明了一个全局变量
db.eval("say()");
<<<
hello
```
![](https://box.kancloud.cn/faf1f96a01da5d73d71d84501f696817_413x223.png)