[TOC]
## 安装
- [mongo官网下载区](https://www.mongodb.com/download-center?jmp=nav#community)
## 设置环境变量
找到mongodb安装目录,一般是 C:\Program Files\MongoDB 2.6 Standard\bin
将它添加进系统环境变量中的path
>计算机>属性>高级>环境变量>path
## 启动数据库服务器
-- port 默认为27017
-- logpath
-- logappend
-- dbpath
-- directoryperdb
### 手动启动
先在你想要存储数据(数据库文档)的地方创建一个文件夹
比如我们想存放在e盘的mongo下
再输入命令
```
//cmd中
mongod --dbpath E:\mdata --logpath E:\mlog --logappend --directoryperdb
```
就会生成一个数据库
![](https://box.kancloud.cn/a24d2e423341e81b3a366e31327ec77d_451x448.png)
>[danger] 用以启动服务端的CMD不能关闭,一旦这个cmd关闭,数据库服务器就会自动关闭
### 用服务器启动
添加服务
>[danger] **注意:** mlog是一个文件,mdata是一个文件夹(需提前创建)
```
//cmd中
mongod.exe --dbpath E:\mdata --logpath E:\mlog --logappend --directoryperdb --serviceName mongodb --install
net start mongodb
net stop mongodb
```
添加`--directoryperdb`会将每个数据库单独作为一个文件夹存放
删除服务
```
sc delete mongodb
```
## 数据库服务器目录分布
- admin数据库
用来管理数据库,数据库有哪些用户,哪些权限,操作哪些集合,是否可读可写等
- local数据库
- Collections 集合文件夹
- startup_log 启动日志集合
![](https://box.kancloud.cn/e6bde8ad45cd5e2c7be3897d0aa202d2_689x138.png)
一个集合有三种形式的视图
...
## 连接数据库
命令窗体中输入 mongo --host=127.0.0.1 或者 mongo 按回车键
```
mongo //一般直接敲回车即可
```
如果出现类似waiting for connections on port 27017就表示启动成功,已经在27017端口上监听了客户端的请求
## mongdb基本概念
![](http://7xjf2l.com1.z0.glb.clouddn.com/mongodbstructure.jpg)
![](http://7xjf2l.com1.z0.glb.clouddn.com/mongovue.png)
- 数据库
MongoDB的单个实例可以容纳多个独立的数据库,比如一个学生管理系统就可以对应一个数据库实例
- 集合
数据库是由集合组成的,一个集合用来表示一个实体,如学生集合
- 文档
集合是由文档组成的,一个文档表示**一条记录**,比如一位同学张三就是一个文档
## 数据库操作
### 注意事项
mongdb中没有单独的创建数据的命令,只能通过`use`切换数据库(即使这个数据库不存在)。
当添加文档时,若一个数据库不存在,或则集合,又或则一个文档不存在,它会自动级联创建。
### 帮助命令
```
db.help();
```
### 显示数据库列表
```
show dbs
```
>我们刚创建的数据库school如果不在列表内, 要显示它,我们需要向school数据库插入一些数据
```
db.students.insert({name:'zfpx',age:1});
```
### 切换数据库
>即使数据库不存在也可以切换,但只有当我们往里插入一个文档的时候才会真正创建该文档。
```
use database_name database_name代表数据库的名字
```
### 查看当前使用的数据库
```
db 或 db.getName()
```
### 删除数据库
```
db.dropDatabase()
```
### 关闭数据库
让数据库服务器关闭
```
use admin;
db.shutdownServer();
```
## 集合操作
### 查看帮助
```
db.students.help() //students是我们自己创的一个集合
```
### 查看数据库下的集合
```
show collections
```
### 创建集合
创建一个空集合
```
db.createCollection(collection_Name)
```
创建集合并插入一个文档
```
db.collection_Name.insert(document)
```
### 删除当前数据下的xx集合
```
db.students.drop() drop the collection ,删除集合
```
## 文档操作
### 默认行为
当我们创建一个文档时,mongdb会自动为这条文档添加一个`_id`属性,它是一个绝对唯一的标识(因为mongdb是一个分布式数据库)
之前我们使用MySQL等关系型数据库时,主键都是设置成自增的。但分布式环境下,这种方法就不可行了,会产生冲突,为此MongDB采用了一个称之为Objectid的类型来做主键。Objectid是一个12字节的BSON类型字符串。按照字节顺序,依次代表:
- 4字节:UNIX时间戳
- 3字节:表示运行MongDB的机器
- 2字节:表示生成此_id的进程
- 3字节:由一个随机数开始的计数器生成的值
但我们也可以手动指定id
```
db.xxx.insert({_id:111,name:'ahhh'});
```
### insert
```
db.collection_name.insert(document)
```
>每当插入一条新文档的时候mongodb会自动为此文档生成一个_id属性,_id一定是唯一的,用来唯一标识一个文档 _id也可以直接指定,但如果数据库中此集合下已经有此_id的话插入会失败
```
> db.students.insert({_id:1,name:'ahhh',age:1});
<<<
WriteResult({ "nInserted" : 1 })
> db.students.insert({_id:1,name:'ahhh',age:1});
```
#### 批量插入
```
var db = connect('school');
var start = Date.now();
for(var i=0;i<1000;++i){
db.students.insert({name:'zfpx'+i,age:i});
}
var cost = (Date.now() - start)/1000+'s';
print('cost:'+cost);
```
推荐使用`insert([{},{}])`数组的形式。
```
var db = connect('school');
var start = Date.now();
var stus = [];
for(var i=0;i<1000;++i){
stus.push({name:'zfpx'+i,age:i});
}
db.students.insert(stus);
var cost = (Date.now() - start)/1000+'s';
print('cost:'+cost);
```
### save
```
db.collection_name.save(document)
```
其中document就是一个`{}`json
>注:如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。
### update
```
db.collection.update(
<query>,
<updateObj>,
{
upsert: <boolean>,
multi: <boolean>
}
)
```
- query 查询条件,指定要更新符合哪些条件的文档
- update 更新后的对象或指定一些更新的操作符
- $set直接指定更新后的值
- $inc在原基础上累加
- upsert 可选,这个参数的意思是,如果不存在符合条件的记录时是否插入updateObj. 默认是false,不插入。
- multi 可选,mongodb 默认只更新找到的第一条记录,如果这个参数为true,就更新所有符合条件的记录。
---
#### 完全替换
默认情况下会将通过query查找到的第一条数据完全**替换**成updateObj
比如下面这个例子
```
//此处示例省略了_id
//原数据{"name":"ahhh","age":"1"}
db.students.update({name:'ahhh'},{age:101})
<<<修改后
{"age":"101"}
```
#### 通过$set操作符更新文档(非替换)
```
db.students.update({name:'ahhh2'},{$set:{age:300}});
```
除此之外`$set`也能给文档添加一个字段
```
db.students.update({name:'ahhh'},{$set:{add:1}});
```
默认是一次只查找一条添加,我们可以通过`multi`属性进行批量操作
```
db.students.update({name:'ahhh'},{$set:{other:1}},{multi:true});
```
如果要更改的字段的值是一个数组,可以通过`.索引`来对数组中某一项进行更改
```
//注意索引是从0开始的
db.students.update({name:'ahhh'},{$set:{hobby.0:'drinking'}});
```
#### $unset删除字段
```
db.students.update({name:'ahhh'},{$unset:{other:1}},{multi:true});
```
#### 自增:$inc
```
db.students.update({name:'ahhh2'},{$inc:{age:2}}); //每次累加2
```
#### upsert
upsert 可选,这个参数的意思是,如果不存在符合条件的记录时是否插入updateObj. 默认是false,不插入
```
db.students.update({name:'ahhh101'},{sex:'female'},{upsert:true});
<<<
//会添加这面一条文档
{"_id":...,"sex":"female"}
```
上面并不会自动插入name字段
如果需要,我们需要配合使用`$set`
```
db.students.update({name:'ahhh000'},{$set:{sex:'female'}},{upsert:true});
<<<
//会添加这面一条文档
{"_id":...,"name":"ahhh000","sex":"female"}
```
##### upsert和 save
```
db.students.save({name:'ahhh'})
db.students.update({name:'ahhh'},{$set:{sex:'female'}},{upsert:true});
```
save会直接创建一条{name:'ahhh'},而update+upsert会先查询是否有一条存在name=ahhh的文档。
#### $push
以数组形式作为值添加到属性
```
db.students.update({name:'ahhh'},{$push:{hooby:'smoking'}});
```
重复命令,会在同一条文档中重复添加 smoking(不会替换,而是追加)
#### $ne
not equal 不相等
只要hobby不是smoking,就会被替换成updateObj
```
db.students.update({hobby:{$ne:'smoking'}},{city:'beijing'});
```
#### $addToSet
如果该属性下存在这个值就略过,如果没有就往这个属性的值数组中追加你设定的值。
```
db.students.update({name:'ahhh'},{$addToSet:{hobby:'drinking'});
```
>[danger] 注意如添加的不是`''`,而是`[]`,则会往数组里添加一个数组
```
//错误的使用方式
db.students.update({name:'ahhh'},{$addToSet:{hobby:['read','play']});
```
应该使用`$each`展开数组
```
//正确的使用方式
db.students.update({name:'ahhh'},{$addToSet:{hobby:$each:['read','play']});
```
#### $pop
删除数组值中的某项
值为1是是删除最后一项,值为-1时是删除第一项
```
db.students.update({name:'ahhh'},{$pop:{hobby:1}});
```
#### var 与 print
```
var r = db.students. update(...)
print(r);
<<<
writeresult
```
#### runCommand
```
//test.js
var cmd = {
findAndModify:'students' //要操作的集合
,query:{name:'ahhh'}
,update:{$set:{age:100}}
,fields:{name:1}
//指定要返回的文档的字段 1|true返回 0|false不返回,默认只有id是默认要返回的,其它都不是
//额外的,如果什么都不指定,表示全返回
,sort:{age:1}
//按age字段进行排序,1为正序,-1倒叙
,new:true
//返回修改后的文档,为false时是更行前的文档
}
var db = connect('school'); //链接到school数据库
var result = db.runCommand(cmd);
printjson(result);
```
然后在命令行运行该脚本
```
mongo test.js
<<<
{
"lastErrorObject" : {
"n" : 1,
"updatedExisting" : true
},
"value" : {
"_id" : ObjectId("5add4f94195168b828292746"),
"name" : "ahhh"
},
"ok" : 1
}
```
另外如果你已经在用客户端连接数据库服务器(已经通过mongo命令连接)
```
load('./test.js');
```
### count
显示当前集合的文档总数
```
db.students.count();
```
### remove
```
db.collection.remove(
<query>,
{
justOne: <boolean>
}
)
```
- query :(可选)删除的文档的条件。
- justOne : (可选)如果设为 true 或 1,则只删除匹配到的多个文档中的第一个
默认会删除所有匹配上的文档
示例:因为使用了justOne参数,So即使匹配多条也只删除一条
```
> db.students.remove({name:"ahhh"},{justOne:true})
WriteResult({ "nRemoved" : 1 })
```