# mongo
- 云棲 - MongoDB資料匯總: https://yq.aliyun.com/articles/4778

**其實用 mongo 做簡單查詢和分頁,還是蠻爽的**
工具推薦:Studio3T,query builder、cli mode、view、sql mode
## MongoDB 基礎教程
> [實驗樓 - 學習路徑 - mongodb 工程師](https://www.shiyanlou.com/paths/mongodb)
基本概念:
- db 數據庫:類似 mysql 中的 db
- document 文檔:類似 mysql 中的 row(行),使用一種類 json 的 bson 存儲數據
- document relation 文檔關聯:include 包含、point 引用
- collection 集合:類似 mysql 中的 table(表),文檔的聚合
- metadata 元數據:類似 mysql 中的 mysql、sys、information_schema 等數據庫存儲的信息(當然沒有那么大的信息量)
- aggregate 聚合:類似 mysql 中的 group by
基本語法:
- 鏈式調用 `db.users.find().pretty().sort().limit().skip()`
- 條件操作符 1:`$or $gt`
- 條件操作符 2:`$type`,指定數據類型
- 原子操作:`$set $unset`,更新指定 key
```
# use docker to test and practice mongo
docker run --name some-mongo -d mongo:3.4
docker exec -ti some-mongo bash
# connect
mongo # 連接到 mongodb
exit / Ctrl-d # 退出
# db
show dbs
use local # create if not exists
db # show the current db
db.dropDatabase() # 'db' reference the current db
# collection
show collections
db.createCollection('users')
db.users.drop()
# document
db.users.insert() / db.users.save() # create collection 'users' if not exists
db.users.update()
db.users.remove()
# find
db.users.find().pretty().sort().limint().skip()
# AND $or
# $gt $lt
# $type
# index
db.users.ensureIndex({"name":1})
# aggregate
db.users.aggregate([{$group:{_id:"$name", user:{$sum:"$user_id"}}}])
db.users.aggregate([{$match:{user_id:{$gt:0,$lte:2}}},{$group:{_id:"user",count:{$sum:1}}}]) // aggreagte with pipe
# 原子操作
# 查詢分析
db.users.find({gender:"M"},{user_name:1,_id:0}).explain()
db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain() // hint() force to use the input as index
# group by
db.cashEventReport.group({
key:{event_id:1, utm_source:1},
cond:{event_id:"1000109"},
reduce: function(curr, res){
res.cnt++;
},
initial: {cnt:0}
});
# distinct
db.crcsCashHitRule.distinct('rule_set_name')
```
$in: 查詢有長度限制
## mongoDB入門篇
> 慕課網 SeanZ http://www.imooc.com/learn/295
相關概念: nosql, 索引, 集合, 復制集, 分片, 數據均衡
部署: 簡單的單機服務 -> 具有冗余容錯功能的復制集 -> 搭建大規模數據集群 -> 集群的自動部署
使用: 最基本的文檔增刪改查, 不同類型的索引創建與使用, 復雜的聚合查詢, 對數據集合分片并在不同分片間維持數據均衡, 數據備份與恢復, 數據遷移
運維: 集群部署; 常見故障: 單點失效如何恢復工作, 數據庫意外殺死如何進行數據恢復, 數據發送拒絕服務時, 如何排查原因, 磁盤快滿時如何處理
## 入門教程
> [mongodb 官方文檔](https://docs.mongodb.com/manual/)
> [菜鳥教程 - mongodb 教程](http://www.runoob.com/mongodb/mongodb-tutorial.html)
> [易百教程 - mongodb 教程](http://www.yiibai.com/mongodb/)
## mongodb 小書
> https://github.com/justinyhuang/the-little-mongodb-book-cn
6個簡單概念: database collection document field index cursor
Mongo的shell運行在JavaScript之上: 全局指令(help exit) 命令列表( db.help() ) -> 這是為什么命令不能少了 ()
```
use learn # 既可以切換, 也可以自動新建
show dbs
db.getName() # 用 db.help() 就可以找到需要的方法了
db.unicorns.insert({name: 'Aurora', gender: 'f', weight: 450})
db.unicorns.remove()
db.unicorns.find()
db.unicorns.find({gender: 'm', weight: {$gt: 700}}) # $gt
db.unicorns.find({vampires: {$exists: false}}) # $exists
db.unicorns.find({gender: 'f', $or: [{loves: 'apple'}, {loves: 'orange'}, {weight: {$lt: 500}}]}) # $or
db.unicorns.find({_id: ObjectId("TheObjectId")}) # _id
db.unicorns.find({str: /far/)}) # string regexp
db.unicorns.find(null, {name: 1, "x.y":1}) # project field 設置
db.unicorns.find().sort({weight: -1}) # sort
db.unicorns.find().sort({weight: -1}).limit(2).skip(1) # page
db.unicorns.count()
db.unicorns.update({name: 'Roooooodles'}, {weight: 590}) # replace
db.unicorns.update({weight: 590}, {$set: {name: 'Roooooodles', dob: new Date(1979, 7, 18, 18, 44), loves: ['apple'], gender: 'm', vampires: 99}}) # $set
db.unicorns.update({name: 'Pilot'}, {$inc: {vampires: -2}}) # $inc
db.unicorns.update({name: 'Aurora'}, {$push: {loves: 'sugar'}}) # $push
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true); # UpSert
db.unicorns.update({}, {$set: {vaccinated: true }}, false, true) # update all
db.unicorns.ensureIndex({name: 1});
db.unicorns.dropIndex({name: 1});
db.unicorns.getIndexs()
db.unicorns.find().explain()
db.getLastError()
# array
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Siona', manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")] })
db.employees.find({manager: ObjectId("4d85c7039ab0fd70a117d730")})
# embedded document
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d734"), name: 'Ghanima', family: {mother: 'Chani', father: 'Paul', brother: ObjectId("4d85c7039ab0fd70a117d730")}})
db.employees.find({'family.mother': 'Chani'})
# denormalization
db.users.insert({name: 'leto', email: 'leto@dune.gov', account: {allowed_gholas: 5, spice_ration: 10}})
# capped collection
db.createCollection('logs', {capped: true, size: 1048576})
# geo
var map = [{"gis":["x":185,"y":150]},{"gis":["x":70,"y":180}]
db.map.ensureIndex({"gis":"2d"},{min:-1,max:201}) # 默認會建立一個[-180,180]之間的2d索引
db.map.find({"gis":{$near:[70,180]}},{gis:1,_id:0}).limit(3) # 查詢點(70,180)最近的3個點
db.map.find({gis:{$within:{$box:[[50,50],[190,190]]}}},{_id:0,gis:1}) # 查詢以點(50,50)和點(190,190)為對角線的正方形的所有的點
db.map.find({gis:{$within:{$center:[[56,80],50]}}},{_id:0,gis:1}) # 查詢出以圓心(56,80),半徑為50的圓中的點
# MapReduce
# sharding copy
db.stats()
db.unicorns.stats()
db.setProfilingLevel(2);
// do something
db.system.profile.find()
# 最近3條慢查詢
db.system.profile.find().sort({$natrual:-1}).limit(3)
# cpu使用率高 https://help.aliyun.com/document_detail/62224.html
# admin
db.currentOp(
{
"waitingForLock" : true,
$or: [
{ "op" : { "$in" : [ "insert", "update", "remove" ] } },
{ "query.findandmodify": { $exists: true } }
]
}
)
db.killOp(opid)
# mongodump mongostore
mongodump --db learn --out backup
mongorestore --collection unicorns backup/learn/unicorns.bson
# mongoimport mongoexport
mongoexport --db learn -collection unicorns # json
mongoexport --db learn -collection unicorns --csv -fields name,weight,vampires
```