[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
```
就會生成一個數據庫

>[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 啟動日志集合

一個集合有三種形式的視圖
...
## 連接數據庫
命令窗體中輸入 mongo --host=127.0.0.1 或者 mongo 按回車鍵
```
mongo //一般直接敲回車即可
```
如果出現類似waiting for connections on port 27017就表示啟動成功,已經在27017端口上監聽了客戶端的請求
## mongdb基本概念


- 數據庫
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 })
```