简介
1. MongoDB介绍
MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL数据库产品中的一种。是 像关系型数据库(MySQL)的非关系型数据库。 它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。
MongoDB中的记录是一个文档,它是一个由字段和值对(field:value)组成的数据结构。MongoDB文档类似于JSON对象,即一个文档认 为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。
2. Redis和MongoDB的区别
Redis,键值对数据库,支持多种数据类型,数据存在内存,可以rdb、aof持久化到硬盘
mongodb文档数据,可以存放xml、json、bson类型系那个的数据。
3. 应用场景
应对“三高”:高并发、高可用
适合场景:事件记录、内容管理或者博客平台,比如评论系统。
具体的应用场景如:
1)社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。 2)游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。 3)物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将 订单所有的变更读取出来。
4)物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。 5)视频直播,使用 MongoDB 存储用户信息、点赞互动信息等。
4. 什么时候选择mongodb
在架构选型上,除了上述的三个特点外,如果你还犹豫是否要选择它?可以考虑以下的一些问题:
应用不需要事务及复杂 join 支持
新应用,需求会变,数据模型无法确定,想快速迭代开发
应用需要2000-3000以上的读写QPS(更高也可以)
应用需要TB甚至 PB 级别数据存储
应用发展迅速,需要能快速水平扩展
应用要求存储的数据不丢失
应用需要99.999%高可用
应用需要大量的地理位置查询、文本查询
如果上述有1个符合,可以考虑 MongoDB,2个及以上的符合,选择 MongoDB 绝不会后悔。
数据库基本使用
# 查看数据库
> show databases
# 选择数据库
> use admin
# 隐式创建,选择不存在的数据库不会报错,后期当该数据库有数据时,系统自动创建
> use admin2
# 删除数据库
> use test2
switched to db test2
> db.dropDatabase()
{ "dropped" : "test2", "ok" : 1 }
集合(文档)的使用
# 查看集合
> show collections
# 创建集合
> db.createCollection('b2')
{ "ok" : 1 }
# 查询单个集合
> db.getCollection('a1')
momoShu.a1
# 删除集合
> db.b2.drop()
true
> show collections
c1
隐式创建db
> use test2
switched to db test2
> show databases
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
> db.createCollection('aa')
{ "ok" : 1 }
> show databases
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
test2 0.000GB
文档的CRUD
增Create
语法:db.集合名.insert(JSON数据)
集合存在直接插入数据,集合不存在则数据隐式创建
> db.c1.insert({name:'momoShu',age:20})
WriteResult({ "nInserted" : 1 })
对象的键统一不加引号,但是查看集合数据时系统会自动加全球唯一id
> db.c2.insert({name:'小明'})
WriteResult({ "nInserted" : 1 })
> show collections
c1
c2
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
在一个集合里面,每个文档都有唯一的"_id"值,来确保集合里面每个文档都能被唯一标识。
- 前4个字节表示时间戳
- 接下来的3个字节是机器标识码
- 紧接的两个字节由进程id组成(PID)
- 最后三个字节是随机数。
也可以自定义id 在插入JSON数据时增加_id的键:你想设的值即可覆盖掉自动生成的(不建议在实战使用)
遍历方式插入多条数据进文档
for循环是一条一条插入,但前九条的提示都看不到,只有最后一条的提示可以显示出来
> for(var i=1;i<=10;i++){
... db.c2.insert({name:'第:'+i,age:i})
... }
WriteResult({ "nInserted" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "第:1", "age" : 1 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "第:2", "age" : 2 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "name" : "第:3", "age" : 3 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "第:4", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
查Read
语法 :db.集合名.find(条件[,要查询的列])
全查
> db.c2.find()
只看age列
> db.c2.find({},{age:2})
{ "_id" : ObjectId("5ea0a590e0020b96979799ac") }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "age" : 1 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "age" : 2 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "age" : 3 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "age" : 10 }
除了age列以外的都显示
> db.c2.find({},{age:0})
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "第:1" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "第:2" }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "name" : "第:3" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "第:4" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10" }
升级版语法 :db.集合名.find({
键:{运算符:值}
})
运算符 | mongo语法 |
---|---|
>大于 | $gt |
<小于 | $lt |
>=大于等于 | $gte |
<= 小于等于 | $lte |
!=不等于 | $ne |
=等于 | $eq |
条件运算符
db.c2.find({age:{$gte:10}})
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
范围内查询in:[ ]
> db.c2.find({age:{$in:[3,5,7]}})
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "name" : "第:3", "age" : 3 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
改Update
语法 :db.集合名.update(条件,新数据[,是否新增,是否修改多条])
第三个参数:是否新增:指条件匹配不到数据则插入(true是插入,false是不插入)
第四个参数:是否修改多条:指将匹配成功的数据都修改(true是,false否-默认)
> db.c2.update({name:'第:1'},{name:'第:2'})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "第:2" } # 这本是第:1
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "第:2", "age" : 2 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "name" : "第:3", "age" : 3 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "第:4", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
**默认语法 : 不是修改而是替换。**用升级语法(修改器)才是修改
语法 :db.集合名.update(条件,新数据),{修改器.{键:值}}
修改器 | 作用 |
---|---|
$inc | 递增 |
$rename | 重名列 |
$set | 修改列值 |
$unset | 删除列 |
通过修改器避免替换数据
把name第:0设置为name:‘aa’
> db.c2.update({name:'第:0'},{$set:{name:'aa'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "第:2", "age" : 2 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "name" : "第:3", "age" : 3 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "第:4", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
> db.c2.update({name:'第:2'},{$set:{name:'bb'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 2 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "name" : "第:3", "age" : 3 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "第:4", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
给age2自增3岁 ==5
> db.c2.update({age:2},{$inc:{age:3}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "name" : "第:3", "age" : 3 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "第:4", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
把name为第:3的列名改为id
> db.c2.update({name:'第:3'},{$rename:{'name':'id'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "age" : 3, "id" : "第:3" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "第:4", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
第三个参数的使用
# 一般第一个参数默认false 找不到就不管
# 因为字段名一样且使用了$set 在这里的true 并没有新增
> db.c2.update({name:'第:4'},{$set:{name:'momoShu'}},true)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "age" : 3, "id" : "第:3" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "momoShu", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
# 因为找不到name:'momoShu' 在这里的第三个参数true 新增有效
> db.c2.update({age:'第:5'},{$set:{name:'momoShu'}},true)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5ea111522d5183ef1ffe60e7")
})
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "age" : 3, "id" : "第:3" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "momoShu", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
{ "_id" : ObjectId("5ea111522d5183ef1ffe60e7"), "age" : "第:5", "name" : "momoShu" }
第四个参数的使用
第一个参数{} 不写条件就是查询所有 第四个参数默认false 只修改一条数据
> db.c2.update({},{$set:{age:10}},false,false)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa" }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "age" : 3, "id" : "第:3" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "momoShu", "age" : 4 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 5 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 8 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 9 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
{ "_id" : ObjectId("5ea111522d5183ef1ffe60e7"), "age" : "第:5", "name" : "momoShu" }
> db.c2.update({},{$set:{age:10}},false,true)
WriteResult({ "nMatched" : 12, "nUpserted" : 0, "nModified" : 10 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "age" : 10, "id" : "第:3" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "momoShu", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 10 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 10 }
{ "_id" : ObjectId("5ea111522d5183ef1ffe60e7"), "age" : 10, "name" : "momoShu" }
符合age:20的修改成age:11 第三个参数为false不新增数据 第四个参数匹配到的多条数据都进行修改
> db.c2.update({name: "第:7"},{$set:{age:7}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明", "age" : 20 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa", "age" : 20 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 20 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "age" : 20, "id" : "第:3" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "momoShu", "age" : 20 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 20 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 20 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 20 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 20 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 20 }
{ "_id" : ObjectId("5ea111522d5183ef1ffe60e7"), "age" : 20, "name" : "momoShu" }
> db.c2.update({name: "第:6"},{$set:{age:6}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 符合age:20的修改成age:11 第三个参数为false不新增数据 第四个参数匹配到的多条数据都进行修改
> db.c2.update({age:20},{$set:{age:11}},false,true)
WriteResult({ "nMatched" : 10, "nUpserted" : 0, "nModified" : 10 })
> db.c2.find()
{ "_id" : ObjectId("5ea0a590e0020b96979799ac"), "name" : "小明", "age" : 11 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ad"), "name" : "aa", "age" : 11 }
{ "_id" : ObjectId("5ea0a804e0020b96979799ae"), "name" : "bb", "age" : 11 }
{ "_id" : ObjectId("5ea0a804e0020b96979799af"), "age" : 11, "id" : "第:3" }
{ "_id" : ObjectId("5ea0a804e0020b96979799b0"), "name" : "momoShu", "age" : 11 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b1"), "name" : "第:5", "age" : 11 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b2"), "name" : "第:6", "age" : 6 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b3"), "name" : "第:7", "age" : 7 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b4"), "name" : "第:8", "age" : 11 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b5"), "name" : "第:9", "age" : 11 }
{ "_id" : ObjectId("5ea0a804e0020b96979799b6"), "name" : "第:10", "age" : 11 }
{ "_id" : ObjectId("5ea111522d5183ef1ffe60e7"), "age" : 11, "name" : "momoShu" }
删Delete
语法 :db.集合名.remove(条件,[,是否删除一条])
# 里面的{}不能省略
> db.c1.remove()
2020-04-23T12:23:10.492+0800 E QUERY [js] uncaught exception: Error: remove needs a query :
DBCollection.prototype._parseRemove@src/mongo/shell/collection.js:357:15
DBCollection.prototype.remove@src/mongo/shell/collection.js:384:18
@(shell):1:1
# c1集合中全部删除 默认false 全部删
> db.c1.remove({})
WriteResult({ "nRemoved" : 1 })
# 是否只删除一条 true是
> db.c2.remove({},true)
WriteResult({ "nRemoved" : 1 }
CRUD使用语法小结
db.集合名.insert(JSON数据)
db.集合名.remove(条件,[,是否删除一条])
db.集合名.update(条件,新数据,[,是否新增,是否修改多条])
(条件,{修改器:键:值})
db.集合名.find(条件,[,需要显示的列])
排序和分页
语法 :db.集合名.find().sort(JSON数据)
键就是要排序的列
-1降序
db.c2.find().sort({age:-1})
{ "_id" : ObjectId("5ea133945d7828e9cb831b16"), "id" : 20, "name" : "lindada20", "sex" : "女", "age" : 20, "school" : "家华花园" }
{ "_id" : ObjectId("5ea133945d7828e9cb831b15"), "id" : 19, "name" : "lindada19", "sex" : "女", "age" : 19, "school" : "家华花园" }
{ "_id" : ObjectId("5ea133945d7828e9cb831b14"), "id" : 18, "name" : "lindada18", "sex" : "女", "age" : 18, "school" : "家华花园" }
1升序
> db.c2.find().sort({age:1})
{ "_id" : ObjectId("5ea133945d7828e9cb831b03"), "id" : 1, "name" : "lindada1", "sex" : "女", "age" : 1, "school" : "家华花园" }
{ "_id" : ObjectId("5ea133945d7828e9cb831b04"), "id" : 2, "name" : "lindada2", "sex" : "女", "age" : 2, "school" : "家华花园" }
{ "_id" : ObjectId("5ea133945d7828e9cb831b05"), "id" : 3, "name" : "lindada3", "sex" : "女", "age" : 3, "school" : "家华花园" }
limit的使用
> db.c2.find().limit(2)
{ "_id" : ObjectId("5ea133945d7828e9cb831b03"), "id" : 1, "name" : "lindada1", "sex" : "女", "age" : 1, "school" : "家华花园" }
{ "_id" : ObjectId("5ea133945d7828e9cb831b04"), "id" : 2, "name" : "lindada2", "sex" : "女", "age" : 2, "school" : "家华花园" }
Limit和Skip一起使用
语法 :db.集合名.find().sort().skip(数字).limit(数字)
skip跳过指定数量(可选)默认是0,limit限制查询的数量
-1 降序并查询显示两条
> db.c2.find().sort({age:-1}).skip(0).limit(2)
{ "_id" : ObjectId("5ea133945d7828e9cb831b16"), "id" : 20, "name" : "lindada20", "sex" : "女", "age" : 20, "scool" : "家华花园" }
{ "_id" : ObjectId("5ea133945d7828e9cb831b15"), "id" : 19, "name" : "lindada19", "sex" : "女", "age" : 19, "scool" : "家华花园" }
# 通过age字段排降序,跳过8条记录,只显示2条
> db.c2.find().sort({age:-1}).skip(8).limit(2)
{ "_id" : ObjectId("5ea133945d7828e9cb831b0e"), "id" : 12, "name" : "lindada12", "sex" : "女", "age" : 12, "school" : "家华花园" }
{ "_id" : ObjectId("5ea133945d7828e9cb831b0d"), "id" : 11, "name" : "lindada11", "sex" : "女", "age" : 11, "school" : "家华花园" }
**实战分页计算: ** skip计算公式:(当前页 - 1) * 每页显示条数
排序和分页的小总结
db.集合名.find()
.sort({列:1/-1}) 排序
.skip(数字) 跳过指定数量
.limit(数字) 限制查询条数
.count() 统计总数量
…
聚合函数
聚合数据,实现统计数据,实现分组统计并返回计算后的数据结果。
有点类似sql语句中的 count(*)。
语法:
db.集合名.aggregate([
{管道:{表达式}}
}])
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
常用管道
$group 将集合中的文档分组
$match 过滤数据,只要输出符合条件的文档
$sort 聚合数据进一步排序
$skip 跳过指定记录条数
$limit 限制集合数据返回文档数
...
常用表达式
常用表达式 | 描述 | 用法 |
---|---|---|
$sum | 计算总和 注意!这里$sum=1同count表示统计 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { s u m : " sum : " sum:"likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { a v g : " avg : " avg:"likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m i n : " min : " min:"likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m a x : " max : " max:"likes"}}}]) |
$push | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { p u s h : " push: " push:"url"}}}]) |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { a d d T o S e t : " addToSet : " addToSet:"url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", first_url : { f i r s t : " first : " first:"url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", last_url : { l a s t : " last : " last:"url"}}}]) |
统计男 女年龄
# 只要使用了group 第一个属性就是_id(因为是固定的) : 表示你要通过哪个字段分
# rs 是我自己自定义的 用$sum表达式: 把哪个字段相加
db.a1.aggregate([ {$group:{ _id:"$sex", rs:{$sum:"$age"} }} ])
{ "_id" : 1, "rs" : 9 }
{ "_id" : 2, "rs" : 6 }
统计男 女总人数
> db.a1.aggregate([ {$group:{ _id:"$sex", rs:{$sum:1} }} ])
{ "_id" : 1, "rs" : 3 }
{ "_id" : 2, "rs" : 2 }
求学生总数和平均年龄
# _id:null就是不分组 总学生数total_num:{$sum:1} total_avg:{$avg:"$age"}列必须加$
> db.a1.aggregate([ {$group:{_id:null, total_num:{$sum:1}, total_avg:{$avg:"$age"} }} ])
{ "_id" : null, "total_num" : 5, "total_avg" : 3 }
查男女人数,按人数升序
# 把第一个管道结果的值作为第二个管道的参数 通过性别分组、总人数 总人数作为参数排序
> db.a1.aggregate([
... {$group:{_id:"$sex",rs:{$sum:1}}},
... {$sort:{rs:1}}
... ])
{ "_id" : 2, "rs" : 2 }
{ "_id" : 1, "rs" : 3 }
> db.a1.aggregate([ {$group:{_id:"$sex",rs:{$sum:1}}}, {$sort:{rs:-1}} ])
{ "_id" : 1, "rs" : 3 }
{ "_id" : 2, "rs" : 2 }
优化索引
简介
-
极大的****提高查询的效率****,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。
-
这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
-
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构
实验目的:
通过大数据量中查一条数据很慢,通过索引来提高查询效率【会占用存储空间】
优点:
提高查询效率,降低数据库的IO成本
通过索引对数据进行排序,降低数据排序的成本,降低CPU的消耗
缺点:
占用磁盘空间,大量索引影响SQL语句效率,每次插入和修改都需要更新索引
创建索引的可选参数
Parameter | Type | Description |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 “background” 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
dropDups | Boolean | **3.0+版本已废弃。**在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false. |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
创建索引
db.集合名.createIndex(待创建索引的列,[,额外选项])
参数:
待创建索引的列:{键:1,…键:-1}
说明:1升序 -1降序 例如:{age:1} 表示创建age索引并按照升序的方式存储
> for(var i=0;i<100000;i++){db.testindex.insert({name:'momoShu'+i,age:i});}
WriteResult({ "nInserted" : 1 })
> db.testindex.count()
100000
> db.testindex.find({name:'momoShu99999'})
{ "_id" : ObjectId("5ea174915d7828e9cb84a1cb"), "name" : "momoShu99999", "age" : 99999 }
# 创建普通索引给name列
> db.testindex.createIndex({'name':1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
# 查看当前索引
> db.testindex.getIndexes()
[
{
"v" : 2, # 给哪个列设置了索引
"key" : {
"_id" : 1
},
"name" : "_id_", # 索引名称,默认系统生成也可以自定义
"ns" : "test.testindex"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "name_1",
"ns" : "test.testindex"
}
]
给索引起别名
db.testindex.createIndex({name:1},{name:'alias_name'})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
db.testindex.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.testindex"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "alias_name",
"ns" : "test.testindex"
}
]
创建复合索引
语法:
db.集合名.createIndex({键:存储方式,键:存储方式})
一次性给两个字段建立索引
一般查询两个条件经常一起出现的而且查询的慢就可以间组合索引
> db.testindex.createIndex({name:1,age:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
> db.testindex.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.testindex"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "alias_name",
"ns" : "test.testindex"
},
{
"v" : 2,
"key" : {
"name" : 1,
"age" : 1
},
"name" : "name_1_age_1",
"ns" : "test.testindex"
}
]
唯一索引
语法:
db.集合名.createindex(待添加参数,{unique:列名})
db.testindex.createIndex({name:1},{unique:'name'})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.testindex.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.testindex"
},
{
"v" : 2,
"unique" : true,
"key" : {
"name" : 1
},
"name" : "name_1",
"ns" : "test.testindex"
}
]
唯一索引 同个字段不能插入已有的值
> db.testindex.insert({name:'lindada'})
WriteResult({ "nInserted" : 1 })
> db.testindex.insert({name:'lindada'})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.testindex index: name_1 dup key: { name: \"lindada\" }"
}
})
> db.testindex.find({name:"lindada"})
{ "_id" : ObjectId("5ea185df5d7828e9cb84a1cc"), "name" : "lindada" }
分析索引explain
> db.testindex.find({name:'momoShu99999'}).explain('executionStats')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.testindex",
"indexFilterSet" : false,
"parsedQuery" : {
"name" : {
"$eq" : "momoShu99999"
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"name" : {
"$eq" : "momoShu99999"
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"executionStats" : { # 执行计划相关特点统计信息
"executionSuccess" : true, # 执行成功的状态
"nReturned" : 1, # 返回结果的集数目
"executionTimeMillis" : 33, # 执行所需要的的时间 毫秒
"totalKeysExamined" : 0, # 索引检查的时间
"totalDocsExamined" : 100000, # 检查文档的总数
"executionStages" : {
"stage" : "COLLSCAN", # 索引扫描的方式
"filter" : { # 过滤条件
"name" : {
"$eq" : "momoShu99999"
}
},
"nReturned" : 1, # 返回结果数目集
"executionTimeMillisEstimate" : 0, # 预估的执行时间
"works" : 100002, # 工作单元数,一个查询会被派生为一些小的工作单元
"advanced" : 1, # 优先返回的结果数目
"needTime" : 100000,
"needYield" : 0,
"saveState" : 781,
"restoreState" : 781,
"isEOF" : 1,
"direction" : "forward", # 方向
"docsExamined" : 100000 # 文档检查数目
}
},
"serverInfo" : {
"host" : "localhost.localdomain",
"port" : 27017,
"version" : "4.2.5",
"gitVersion" : "2261279b51ea13df08ae708ff278f0679c59dc32"
},
"ok" : 1
}
ps:
COLLSCAN 全盘扫描
IXSCAN 索引扫描
FETCH 根据索引去检索指定document
加索引后 只要1秒
> db.testindex.createIndex({age:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
> db.testindex.find({name:'momoShu99999'}).explain('executionStats')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.testindex",
"indexFilterSet" : false,
"parsedQuery" : {
"name" : {
"$eq" : "momoShu99999"
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"name" : 1
},
"indexName" : "name_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"name" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"name" : [
"[\"momoShu99999\", \"momoShu99999\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 0,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"docsExamined" : 1,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"keyPattern" : {
"name" : 1
},
"indexName" : "name_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"name" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"name" : [
"[\"momoShu99999\", \"momoShu99999\"]"
]
},
"keysExamined" : 1,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
},
"serverInfo" : {
"host" : "localhost.localdomain",
"port" : 27017,
"version" : "4.2.5",
"gitVersion" : "2261279b51ea13df08ae708ff278f0679c59dc32"
},
"ok" : 1
}
如何选择合适的列创建索引
为常做条件、排序】分组的字段建立索引
选择唯一性索引 ps:同值较少 比如性别字段
选择较小的数据列,为较长的字符串使用前缀索引 ps:索引文件更小占用磁盘空间更少
删除索引
语法:
db.集合名.dropIndex(索引名)
> db.testindex.dropIndex('name_1')
{ "nIndexesWas" : 2, "ok" : 1 }
给name创建索引并起别名
> db.testindex.createIndex({name:1},{name:'alias_name'})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.testindex.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.testindex"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "alias_name",
"ns" : "test.testindex"
}
]
删除全部索引
系统的是不能删的。系统的还在
> db.testindex.dropIndexes()
{
"nIndexesWas" : 3,
"msg" : "non-_id indexes dropped for collection",
"ok" : 1
}
查看索引
语法:
db.集合名.getIndexes()
备份/还原数据
mongodump -h -port -p -u -d -o
# -h host 服务器ip地址(一般不写 默认本机)
# -port 端口(一般不写 默认27017)
# -u user 账号
# -p pwd 密码
# -d database (数据库不写则导出全部)
# -o open 备份到指定目录下
备份数据 导出mongo的文档
还原(恢复)数据
语法:
mongorestore -h -port -u -p -d --drop 备份数据目录
# -h -port -u -p 同上
# -d 不写则还原全部数据
# --drop 先删除数据库再导入 不写则覆盖
# 恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!
我现在把test数据库删了
使用该命令恢复以及删除了的数据
查看我刚删的库是否存在
查询我的10w条数据是否有还原到真实存在
表示成功还原拉