mongodb笔记
nosql介绍
“NoSQL”⼀词最早于1998年被⽤于⼀个轻量级的关系数据库的名字
随着web2.0的快速发展, NoSQL概念在2009年被提了出来
NoSQL在2010年⻛⽣⽔起, 现在国内外众多⼤⼩⽹站, 如facebook、 google、 淘宝、 京东、 百度等, 都在使⽤nosql开发⾼性能的产品
对于⼀名程序员来讲, 使⽤nosql已经成为⼀条必备技能
NoSQL最常⻅的解释是==“non-relational”, “Not Only SQL”==也被很多⼈接受, 指的是⾮关系型的数据库
关系型与非关系对比
mongodb优势:
- 易扩展:
NoSQL数据库种类繁多, 但是⼀个共同的特点都是去掉关系数据库的关系型特性。 数据之间⽆关系, 这样就⾮常容易扩展 - ⼤数据量, ⾼性能:
NoSQL数据库都具有⾮常⾼的读写性能, 尤其在⼤数据量下, 同样表现优秀。 这得益于它的⽆关系性, 数据库的结构简单 - 灵活的数据模型:
NoSQL⽆需事先为要存储的数据建⽴字段, 随时可以存储⾃定义的数据格式。 ⽽在关系数据库⾥, 增删字段是⼀件⾮常麻烦的事情。 如果是⾮常⼤数据量的表, 增加字段简直就是⼀个噩梦
mongodb
mongodb安装
安装方法一
sudo apt-get install -y mongodb-org
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
查看帮助:mongod –help
启动:sudo service mongod start
停止:sudo service mongod stop
重启:sudo service mongod restart
查看是否启动成功:ps ajx|grep mongod
配置文件的位置:/etc/mongod.conf,
默认端⼝:27017
日志的位置:/var/log/mongodb/mongod.log
安装方法二
启动方法
sudo mongod --config /usr/local/mongodb/mongod.conf
查看是否启动
ps -ef |grep mongod
mongodb 客户端
启动本地客户端:mongo
查看帮助:mongo –help
退出:exit或者ctrl+c
基础命令
数据库
查看当前的数据库:db
查看所有的数据库:show dbs /show databases
切换(创建)数据库:use db_name
删除当前的数据库:db.dropDatabase()
集合
不手动创建集合:
向不存在的集合中第⼀次加⼊数据时, 集合会被创建出来
手动创建结合:
db.createCollection(name,options)
db.createCollection("stu")
db.createCollection("sub", { capped : true, size : 10 } )
参数capped: 默认值为false表示不设置上限,值为true表示设置上限
参数size: 当capped值为true时, 需要指定此参数, 表示上限⼤⼩,当⽂档达到上限时, 会将之前的数据覆盖, 单位为字节
查看集合:show collections
删除集合:db.集合名称.drop()
数据类型
注意点
增删改
插入
db.集合名称.insert(document)
db.stu.insert({name:'gj',gender:1})
db.stu.insert({_id:"20170101",name:'gj',gender:1})
插⼊⽂档时, 如果不指定_id参数, MongoDB会为⽂档分配⼀个唯⼀的ObjectId
查询
db.集合名称.find()
保存
db.集合名称.save(document)
如果⽂档的_id已经存在则修改, 如果⽂档的_id不存在则添加
更新
db.集合名称.update(<query> ,<update>,{multi: <boolean>})
参数query:查询条件
参数update:更新操作符
参数multi:可选, 默认是false,表示只更新找到的第⼀条记录, 值为true表示把满⾜条件的⽂档全部更新
db.stu.update({name:'hr'},{name:'mnc'}) 更新一条
db.stu.update({name:'hr'},{$set:{name:'hys'}}) 更新一条
db.stu.update({},{$set:{gender:0}},{multi:true}) 更新全部
注意:“multi update only works with $ operators”
删除
db.集合名称.remove(<query>,{justOne: <boolean>})
参数query:可选,删除的⽂档的条件
参数justOne:可选, 如果设为true或1, 则只删除⼀条, 默认false, 表示删除多条
高级查询
⽅法find
⽅法find(): 查询
db.集合名称.find({条件⽂档})
⽅法findOne():查询,只返回第⼀个
db.集合名称.findOne({条件⽂档})
⽅法pretty(): 将结果格式化
db.集合名称.find({条件⽂档}).pretty()
运算符
比较
等于: 默认是等于判断, 没有运算符
⼩于:$lt (less than)
⼩于等于:$lte (less than equal)
⼤于:$gt (greater than)
⼤于等于:$gte
不等于:$ne
db.stu.find({age:{$gte:18}})
范围
使⽤"$in", "$nin" 判断是否在某个范围内
查询年龄为18、 28的学⽣
db.stu.find({age:{$in:[18,28]}})
逻辑
and:在json中写多个条件即可
查询年龄⼤于或等于18, 并且性别为true的学⽣
db.stu.find({age:{$gte:18},gender:true})
or:使⽤$or, 值为数组, 数组中每个元素为json
查询年龄⼤于18, 或性别为false的学⽣
db.stu.find({$or:[{age:{$gt:18}},{gender:false}]})
查询年龄⼤于18或性别为男⽣, 并且姓名是郭靖
db.stu.find({$or:[{age:{$gte:18}},{gender:true}],name:'gj'})
支持正则
使⽤//或$regex编写正则表达式
查询姓⻩的学⽣
db.stu.find({name:/^⻩/})
db.stu.find({name:{$regex:'^⻩'}})
limit和skip
⽅法limit(): ⽤于读取指定数量的⽂档
db.集合名称.find().limit(NUMBER)
查询2条学⽣信息
db.stu.find().limit(2)
⽅法skip(): ⽤于跳过指定数量的⽂档
db.集合名称.find().skip(NUMBER)
db.stu.find().skip(2)
同时使用
db.stu.find().limit(4).skip(5)
或
db.stu.find().skip(5).limit(4)
自定义查询*
使⽤$where后⾯写⼀个函数, 返回满⾜条件的数据
查询年龄⼤于30的学⽣
db.stu.find({
$where:function() {
return this.age>30;}
})
投影
在查询到的返回结果中, 只选择必要的字段
db.集合名称.find({},{字段名称:1,…})
参数为字段与值, 值为1表示显示, 值为0不显
特殊: 对于_id列默认是显示的, 如果不显示需要明确设置为0
db.stu.find({},{_id:0,name:1,gender:1})
排序
⽅法sort(), ⽤于对 集进⾏排序
db.集合名称.find().sort({字段:1,…})
参数1为升序排列
参数-1为降序排列
根据性别降序, 再根据年龄升序
db.stu.find().sort({gender:-1,age:1})
统计
⽅法count()⽤于统计结果集中⽂档条数
db.集合名称.find({条件}).count()
db.集合名称.count({条件})
db.stu.find({gender:true}).count()
db.stu.count({age:{$gt:20},gender:true})
去重
⽅法distinct()对数据进⾏去重
db.集合名称.distinct('去重字段',{条件})
db.stu.distinct('hometown',{age:{$gt:18}})
数据备份与修复
备份的语法:
mongodump -h dbhost -d dbname -o dbdirectory
-h: 服务器地址, 也可以指定端⼝号
-d: 需要备份的数据库名称
-o: 备份的数据存放位置, 此⽬录中存放着备份出来的数据
mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1bak
恢复语法:
mongorestore -h dbhost -d dbname --dir dbdirectory
-h: 服务器地址
-d: 需要恢复的数据库实例
–dir: 备份数据所在位置
mongorestore -h 192.168.196.128:27017 -d test2 --dir ~/Desktop/test1bak/test1
聚合 aggregate
聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。
db.集合名称.aggregate({管道:{表达式}})
常用管道
在mongodb中,⽂档处理完毕后, 通过管道进⾏下⼀次处理
常用管道如下:
$group: 将集合中的⽂档分组, 可⽤于统计结果
$match: 过滤数据, 只输出符合条件的⽂档
$project: 修改输⼊⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果
$sort: 将输⼊⽂档排序后输出
$limit: 限制聚合管道返回的⽂档数
$skip: 跳过指定数量的⽂档, 并返回余下的⽂档
$unwind: 将数组类型的字段进⾏拆分
表达式
处理输⼊⽂档并输出
语法:表达式:’$列名’
常⽤表达式:
$sum: 计算总和, $sum:1 表示以⼀倍计数
$avg: 计算平均值
$min: 获取最⼩值
$max: 获取最⼤值
$push: 在结果⽂档中插⼊值到⼀个数组中
$first: 根据资源⽂档的排序获取第⼀个⽂档数据
$last: 根据资源⽂档的排序获取最后⼀个⽂档数据
group
group文档:https://docs.mongodb.com/manual/reference/operator/aggregation/group/
group by null
$ project
$match
$sort
$ limit
$ skip
$unwind
将⽂档中的某⼀个数组类型字段拆分成多条, 每条包含数组中的⼀个值
语法:db.集合名称.aggregate({ u n w i n d : ′ unwind:' unwind:′字段名称’})
db.t2.insert({_id:1,item:'t-shirt',size:['S','M','L']})
db.t2.aggregate({$unwind:'$size'})
结果如下:
{ "_id" : 1, "item" : "t-shirt", "size" : "S" }
{ "_id" : 1, "item" : "t-shirt", "size" : "M" }
{ "_id" : 1, "item" : "t-shirt", "size" : "L" }
重点
### mongodb插入数据
- db.collecion.insert({}) 插入数据,`_id`存在就报错
- db.collection.save({}) 插入数据,`_id`存在会更新
### mongodb的更新操作
- `db.test1000.update({name:"xiaowang"},{name:"xiaozhao"})`
- 把name为xiaowang的数据替换为`{name:"xiaozhao"}`
- `db.test1000.update({name:"xiaohong"},{$set:{name:"xiaozhang"}})`
- 把name为xiaowang的数据name的值更新为xiaozhang
- `db.test1000.update({name:"xiaozhang"},{$set:{name:"xiaohong"}},{multi:true})`
- `{multi:true}`达到更新多条的目的
### mongodb删除
- `db.test1000.remove({name:"xiaohong"},{justOne:true})`
- 默认情况会删除所有满足条件的数据,`{justOne:true}`能达到只删除一条的效果
### mongodb的count方法
- `db.collection.find({条件}).count()`
- `db.collection.count({})`
### mongodb的投影
- 投影:选择返回结果的字段
- `db.collection.find({条件},{name:1,_id:0})`
- 1.`_id`默认会显示,置为0不显示
- 2.出了`_id`之外的其他字段,如果不显示,不写,不能写为0
### $group的注意点
- `$group`对应的字典中有几个键,结果中就有几个键
- 分组依据需要放到`_id`后面
- 取不同的字段的值需要使用$,`$gender`,`$age`
- 取字典嵌套的字典中的值的时候`$_id.country`
- 能够同时按照多个键进行分组`{$group:{_id:{country:"$country",province:"$province"}}}`
- 结果是:`{_id:{country:"",province:""}`
### 编辑器写mongodb语句
db.stu.find(
{$or:[{age:{$gte:20}},{hometown:{$in:["桃花岛","华⼭"]}}]}
)
#按照gender进行分组,获取不同组数据的个数和平均年龄
db.stu.aggregate(
{$group:{_id:"$gender",count:{$sum:1},avg_age:{$avg:"$age"}}},
{$project:{gender:"$_id",count:1,avg_age:"$avg_age",_id:0}}
)
# 按照hometown进行分组,获取不同组的平均年龄
db.stu.aggregate(
{$group:{_id:"$hometown",mean_age:{$avg:"$age"}}}
)
#使用$group统计整个文档
db.stu.aggregate(
{$group:{_id:null,count:{$sum:1},mean_age:{$avg:"$age"}}}
)
#选择年龄大于20的学生,观察男性和女性有多少人
db.stu.aggregate(
{$match:{$or:[{age:{$gt:20}},{hometown:{$in:["蒙古","⼤理"]}}]}},
{$group:{_id:"$gender",count:{$sum:1}}},
{$project:{_id:0,gender:"$_id",count:1}}
)
db.tv3.aggregate(
{$group:{_id:{country:"$country",province:"$province",userid:"$userid"}}},
{$group:{_id:{country:"$_id.country",province:"$_id.province"},count:{$sum:1}}},
{$project:{country:"$_id.country",province:"$_id.province",count:1,_id:0}}
)