# mongo
- 云栖 - MongoDB资料汇总: https://yq.aliyun.com/articles/4778
![高可用架构杂志第二期:不一样的数据库 - 数据库深度解析:从 NoSQL 的历史看未来](http://qiniu.daydaygo.top/nosql-history.jpg)
**其实用 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
```