mongoDB常用命令
安裝
mongoDB官網下載安裝(Windows安裝方法)
基礎知識
集合——對應關係數據庫中的表
文檔——對應關係數據庫中的行
啓動數據庫服務
定位到安裝目錄下的bin文件夾裏後
> mongod --dbpath ../data/db
如沒有data/db
文件夾,需先創建,dbpath
用於指定數據存放位置
開啓一個客戶端訪問數據庫
同樣的bin文件夾下執行
> mongo
默認連接至test
數據庫
顯示幫助
> help
顯示所有數據庫名稱
> show dbs
切換數據庫
> use test
顯示當前連接的數據庫名稱
> db
顯示當前數據庫所有集合
> show collections
顯示數據庫支持的方法
> db.help()
顯示集合支持的方法
> db.users.help()
創建集合
> db.createCollection("users")
插入操作insert
> db.users.insert({"name":"kiinlam","age":28})
查詢操作find
查找所有文檔
> db.users.find()
查找指定文檔
> db.users.find({"name":"kiinlam"})
查詢一條
> db.users.findOne({"name":"kiinlam"})
大於$gt
> db.users.find({"age":{$gt:22}})
大於等於$gte
> db.users.find({"age":{$gte:22}})
小於$lt
> db.users.find({"age":{$lt:22}})
小於等於$gte
> db.users.find({"age":{$lte:22}})
不等於$ne
> db.users.find("age":{$ne:22})
或$or
> db.users.find({$or:[{"name":"kiinlam"},{"name":"cheungkiinlam"}]})
在集合中$in
> db.users.find("name":{$in:["kiinlam","cheungkiinlam"]})
不在集合中$nin
> db.users.find("name":{$nin:["kiinlam","cheungkiinlam"]})
正則查詢
> db.users.find({"name":/^k/,"name":/m$/})
篩選查詢$where
// 使用js function作爲篩選條件> db.users.find({$where: function(){return this.name=='kiinlam'}})
限制查詢數量limit
> db.users.find({"age":22}).limit(10)
更新操作update
指定文檔全部更新,等於覆蓋
> db.users.update({"name":"kiinlam"}, {"name":"cheungkiinlam","age":27})
局部更新一:增量更新$inc
// age增加2,其他不變> db.users.update({"name":"kiinlam"}, {$inc:{"age":2}})
局部更新二:字段修改$set
// age改爲20> db.users.update({"name":"kiinlam"}, {$set:{"age":20}})
新增更新:如果不存在,就新增一條
// 第三個參數爲true> db.users.update({"name":"kiinlam"}, {$set:{"age":18}}, true)
批量更新
// 如果匹配多條,默認只改第一條,將第四個參數設爲true可全部更新> db.users.update({"name":"kiinlam"}, {$set:{"age":18}}, true, true)
保存操作save
// 插入新文檔,如果不提供"_id"字段> db.users.save({"name":"kiinlam", "age":28})// 更新已存在的文檔> db.users.save({"_id":"xxx","name":"kiinlam", "age":28})
刪除操作remove
刪除操作不可恢復
刪除所有,但不刪除索引
> db.users.remove({})
刪除指定文檔
> db.users.remove({"name":"kiinlam"})
刪除一條指定文檔,如果有多條結果
> db.users.remove({"name":"kiinlam"}, true)
完全刪除集合,包括索引,應當使用drop
大量刪除時,採用複製需要保留的文檔到新集合,再用drop
刪除集合。
刪除數據庫
> db.dropDatabase()
刪除集合
> db.users.drop()
計數操作count
> db.users.count()> db.users.count({"age":29})
唯一值查詢distinct
指定字段有多個相同時,只取一個,返回指定字段的值組合成的數組
> db.users.distinct("age")
分組操作group
按照age
進行分組操作,分組結果存放在user
中,值爲對應age
的name值的數組
key
:分組依據
initial
:初始化函數,每個不同的age組共享同一個函數
$reduce
: 第一個參數爲當前文檔,第二參數爲前一次函數操作的累計對象,第一次爲initial
對應的對象
> db.users.group({ "key": {"age": true}, "initial": {"user": []}, "$reduce": function(cur,prev){ prev.user.push(cur.name); } })
假設有數據如下:
{ "_id" : ObjectId("55910457607379845607d9e2"), "name" : "kiinlam", "age" : 29 }{ "_id" : ObjectId("55910468607379845607d9e3"), "name" : "shadow", "age" : 26 }{ "_id" : ObjectId("55910992607379845607d9e5"), "name" : "foo", "age" : 29 }{ "_id" : ObjectId("55911fca607379845607d9e6"), "name" : "dd", "age" : 22 }{ "_id" : ObjectId("55911fd3607379845607d9e7"), "name" : "mm", "age" : 22 }{ "_id" : ObjectId("55911fdf607379845607d9e8"), "name" : "gg", "age" : 22 }{ "_id" : ObjectId("55911feb607379845607d9e9"), "name" : "jj", "age" : 22 }{ "_id" : ObjectId("55920545ff40738c1fd0a839"), "name" : "zz", "age" : 1 }
分組結果爲:
[ { "age" : 29, "user" : [ "kiinlam", "foo" ] }, { "age" : 26, "user" : [ "shadow" ] }, { "age" : 22, "user" : [ "dd", "mm", "gg", "jj" ] }, { "age" : 1, "user" : [ "zz" ] }]
更多分組功能
可選參數: condition
和 finalize
。
`condition` —— 過濾條件`finalize` —— 函數,分組完成後執行
過濾掉age
大於22的文檔,增加屬性標明分組中文檔的數量
> db.users.group({ "key": {"age": true}, "initial": {"user": []}, "$reduce": function(cur,prev){ prev.user.push(cur.name); }, "condition": {"age":{$lte:22}}, "finalize": function(out){ out.count = out.user.length; } })
分組結果爲:
[ { "age" : 22, "user" : [ "dd", "mm", "gg", "jj" ], "count" : 4 }, { "age" : 1, "user" : [ "zz" ], "count" : 1 }]
mapReduce
map
:映射函數,內部調用emit(key,value)
,集合按照key
進行映射分組。
reduce
:簡化函數,對map
分組後的數據進行分組簡化,reduce(key,value)
中的key
是emit
中的key
,而value
則是emit
分組結果的集合。
mapReduce
:最後執行的函數,參數爲map
、reduce
和一些可選參數。
> db.users.mapReducefunction ( map , reduce , optionsOrOutString ){ var c = { mapreduce : this._shortName , map : map , reduce : reduce }; assert( optionsOrOutString , "need to supply an optionsOrOutString" ) if ( typeof( optionsOrOutString ) == "string" ) c["out"] = optionsOrOutString; else Object.extend( c , optionsOrOutString ); var raw = this._db.runCommand( c ); if ( ! raw.ok ){ __mrerror__ = raw; throw Error( "map reduce failed:" + tojson(raw) ); } return new MapReduceResult( this._db , raw );}
創建map
函數
function (){ emit(this.name,{count:1});}
創建reduce
函數
function (key,value){ var result = {count:0}; for(var i = 0; i < value.length; i++){ result.count += value[i].count; } return result;}
執行mapReduce
操作
> db.users.mapReduce(map,reduce,{"out":"collection"})
假設有數據如下
{ "_id" : ObjectId("55910457607379845607d9e2"), "name" : "kiinlam", "age" : 29 }{ "_id" : ObjectId("55910468607379845607d9e3"), "name" : "shadow", "age" : 26 }{ "_id" : ObjectId("55910992607379845607d9e5"), "name" : "foo", "age" : 29 }{ "_id" : ObjectId("55920545ff40738c1fd0a839"), "name" : "zz", "age" : 1 }{ "_id" : ObjectId("55911fca607379845607d9e6"), "name" : "foo", "age" : 22 }{ "_id" : ObjectId("55911fd3607379845607d9e7"), "name" : "foo", "age" : 22 }{ "_id" : ObjectId("55911fdf607379845607d9e8"), "name" : "foo", "age" : 22 }{ "_id" : ObjectId("55911feb607379845607d9e9"), "name" : "foo", "age" : 22 }
輸出結果
{ "result" : "collection", // 存放最終結果的集合名 "timeMillis" : 28, "counts" : { "input" : 8, // 傳入文檔的次數 "emit" : 8, // emit函數被調用次數 "reduce" : 1, // reduce函數被調用次數 "output" : 4 // 最後返回文檔的個數 }, "ok" : 1}
查看集合collection
中的結果
> db.collection.find()
輸出結果
{ "_id" : "foo", "value" : { "count" : 5 } }{ "_id" : "kiinlam", "value" : { "count" : 1 } }{ "_id" : "shadow", "value" : { "count" : 1 } }{ "_id" : "zz", "value" : { "count" : 1 } }
遊標
遊標只表示一個引用,並不是真正的執行,在需要的時候,通過for循環或next()
方法進行遍歷讀取,枚舉結束後,遊標銷燬,不再返回數據。
申明一個遊標
> var list = db.collection.find()
通過forEach
遍歷遊標
> list.forEach(function(i){ print(i._id); })
輸出結果
fookiinlamshadowzz
或者通過next
遍歷集合
> var list = db.collection.find()> list.next(){ "_id" : "foo", "value" : { "count" : 5 } }> list.next(){ "_id" : "kiinlam", "value" : { "count" : 1 } }> list.next(){ "_id" : "shadow", "value" : { "count" : 1 } }> list.next(){ "_id" : "zz", "value" : { "count" : 1 } }> list.next()2015-07-01T11:27:38.186+0800 E QUERY Error: error hasNext: false at Error (<anonymous>) at DBQuery.next (src/mongo/shell/query.js:255:15) at (shell):1:6 at src/mongo/shell/query.js:255> list>
索引ensureIndex
建立索引
// 1爲升序,-1爲降序> db.users.ensureIndex({"name":1})
唯一索引
> db.users.ensureIndex({"name":1},{"unique":true})
組合索引
> db.users.ensureIndex({"name":1, "age":-1})
查看索引
> db.users.getIndexes()
按指定索引查詢
> db.users.find({"name":"kiinlam"}).hint({"name":1,"age":1})
刪除索引
// 刪除所有自定義索引> db.users.dropIndexes()// 刪除指定索引> db.users.dropIndex("name_1")
性能分析函數explain
> db.users.find().explain("executionStats")
主從數據庫部署
創建主數據庫master
> mongod --dbpath=XXX --master
創建從數據庫slave
// 指定從數據庫端口--port// 指定主數據庫源--source> mongod --dbpath=XXX --port=8888 --slave --source=127.0.0.1:27017
後期指定主數據庫源
> mongod --dbpath=XXX --port=8888 --slave// 後期添加源// 切換到local數據庫> use local// 在sources中加入源地址> db.sources.insert({"host":"127.0.0.1:27017"})
副本集replSet
該架構沒有特定的主數據庫,一個數據庫宕機了,另一個數據庫會頂上
創建第一個數據庫服務器
// 需要指定集羣名及下一個數據庫地址> mongod --dbpath=XXX --port 2222 --replSet mySet/127.0.0.1:3333
創建第二個數據庫服務器
> mongod --dbpath=XXX --port 3333 --replSet mySet/127.0.0.1:2222
初始化副本集
// 進入任一數據庫的admin集合> mongo 127.0.0.1:2222/admin// 執行初始化操作> db.runCommand({ "replSetInitiate":{ "_id":"mySet", "members":[ { "_id":1, "host":"127.0.0.1:2222" }, { "_id":2, "host":"127.0.0.1:3333" } ] } })
仲裁服務器
// 啓動仲裁服務器> mongod --dbpath=XXX --port 4444 --replSet mySet/127.0.0.1:2222// 回到admin集合中添加仲裁服務器> mongo 127.0.0.1:2222/admin> rs.addArb("127.0.0.1:4444")// 查看服務器集羣狀態> rs.status()
分片技術
將集合進行拆分,將拆分的數據均攤到幾個分片上。
主要參與者:
- 客戶端
- 路由服務器mongos
- 配置服務器
- 分片數據庫實例
開啓配置服務器config
> mongod --dbpath=XXX --port 2222
開啓路由服務器mongos
// 指定配置服務器> mongos --port 3333 --configdb=127.0.0.1:2222
開啓分片數據庫服務器mongod
> mongod --dbpath=XXX --port 4444> mongod --dbpath=XXX --port 5555
服務配置
// 進入mongos數據庫admin集合> mongo 127.0.0.1:3333/admin// 添加分片服務器addshard> db.runCommand({ "addshard":"127.0.0.1:4444", "allowLocal":true })> db.runCommand({ "addshard":"127.0.0.1:5555", "allowLocal":true })// 開啓數據庫test的分片功能enablesharding> db.runCommand({"enablesharding":"test"})// 指定集合中分片的片鍵users.name> db.runCommand({"shardcollection":"test.users","key":{"name":1}})// 在mongos中查看數據分片情況> use test> db.printShardingStatus()
運維
運維通常會涉及到以下4個方面
- 安裝部署
- 狀態監控
- 安全認證
- 備份和恢復
安裝部署爲windows服務
// 指定日誌路徑,添加install參數> mongod --dbpath=XXX --logpath=XXX --port=2222 --install// 啓動服務> net start MongoDB
狀態監控
靜態統計
db.stats()
// 查看單個數據庫狀態> db.stats()
stats
比較簡單,可以參考db.stats()一文
db.serverStatus()
// 查看整個mongodb的狀態// 進入admin集合> mongo 127.0.0.1:2222/admin// 查看狀態> db.serverStatus()
serverStatus
的參數很多,可以參考db.serverStatus()一文
實時統計
> mongostat --port 2222
安全認證
TODO
有點複雜,偷懶了,參考安全認證
備份和恢復
// 備份test數據庫到D:\mongodb\backup> mongodump --port 2222 -d test -o D:\mongodb\backup// 恢復數據,drop表示恢復前刪除原有數據> mongorestore --port 2222 -d test --drop D:\mongodb\backup