1、MongoDB概念介绍
MongoDB 是由C++语言编写,基于分布式文件存储的开源数据库系统,将数据存储为一个文档。数据由键值对构成,类似于Json对象。
一个mongoDB中可以建立多个数据库,默认数据库为“db”,每一个都有自己的集合权限,有些数据库名是可以保留的,可以直接访问这些有特殊作用的数据库。
admin:从权限上看,这是root数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库去权限。
local:这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
congfig:当mongodb分片设置时,config数据库的内部使用,用于保存分片的相关信息
文档:文档是键值对,文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,但是mongodb区分类型和大小写
{
name:"shanghai",
age:10,
adress:["xuhui","jingan","huangpu"],
lesson:["java","c","web"]
}
集合:存在于数据库中,没有固定结构
>db.test.insert({"name":"zhangsan"})
>db.test.insert({"name":"lisi","age":20})
数据类型:string,integer,boolean,double,min/max keys ,arrays,timestamp,object,null,symbol,
date,objectID,binary data,code,regular expression
2、安装
下载地址:https://www.mongodb.com/download-center#community
安装MongoDB,在F盘创建一个数据目录F:\mongodb_data
启动服务器:
方法1:在MongoDB的bin目录中执行mongod.exe
方法2:配置环境变量,例如:path:F:\software\mongodb3.4\bin
这样无需切换路径,直接以cmd命令启动服务器
mongod --dbpath D:\mongod_data
cmd启动客户端: mongo localhost:27017
3、与关系型数据库对
sql术语 mongoDB术语 说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接/mongodb不支持
primary key primary key 主键/mongodb自动将id字段设置为主键
4、创建数据库、删除数据库、删除集合命令---基于客户端,mongoDB也有图形化界面,自行安装Robo 3T 1.1.1 ,连接服务器即可
>use mydb 如果数据库不存在则创建,如果存在则切换到指定数据库
>show dbs 查看当前有哪些数据库
>db.myCollection.insert({"name":"lisi","age":20}) 隐式创建
>db.creatCollection(colName) 显示创建
>db.dropDatabase() 删除当前数据库
>db.myCollection.drop() 删除集合
>db 查看当前数据库名称
>show collection 或者 show tables 查看有哪些集合
>db.myCollection.save({"name":"lisi","age":20}) 与insert功能相同
>db.myCollection.insertOne({"name":"lisi","age":20})
>db.myCollection.insertMany({"name":"1","age":20},{"name":"2","age":20},{"name":"3","age":20})
>db.myCollection.find().pretty() 格式化显示数据
db.myCollection.remove({条件},{just one})
>db.myCollection.remove({"name":"lisi"},true) 多条数据只删除一个
>db.myCollection.remove({"name":"lisi"},flase) 多条数据都删除
>db.myCollection.remove({}) 删除所有数据
5、查询文档
db.colName.find(query,projection)
query:可选,使用查询操作符指定查询条件
projection:可选,是用投影操作指定返回的键,查询时返回文档中所有键值,省略该参数即可
db.colName.findOne(query,projection)
1)MongoDB的条件语句查询
操作 格式 范例
等于 {key:value} db.myCollection.find({"math":85}).pretty()
小于 {key:{$lt:value} db.myCollection.find({"math":{$lt:85}).pretty()
小于等于 {key:{$lte:value} db.myCollection.find({"math":{$lte:85}).pretty()
大于 {key:{$gt:value} db.myCollection.find({"math":{$gt:85}).pretty()
大于等于 {key:{$gte:value} db.myCollection.find({"math":{$gte:85}).pretty()
不等于 {key:{$ne:value} db.myCollection.find({"math":{$ne:85}).pretty()
2)and 与 or
and 条件 db.myCollection.find({key:value,......}).pretty()
or 条件 db.myCollection.find({$or:[{key1:value1},{key2:value2}]}).pretty()
联合使用 db.myCollection.find({"math":{$gt:85},$or:[{key1:value1},{key2:value2}]).pretty()
例:>db.person.find({sex:"man",$or[{sarlary:{$gt:6000}},{high:{$gt:178}}],{id:0,name:1,high:1,sarlary:1}})
男性且工资高于6000或身高大于178的人
3)$type操作符
如果想获取“col"集合中title为String的数据,可以使用以下命令:db.col.find({"title":{$type:2}})
>db.person.insert({sex:0},name:"zhangsan")
>db.person.insert({sex:1},name:"lisi")
>db.person.find({sex:{$type:1}},{_id:0,name:1}) _id:0 该列不显示,不写的话默认id都是显示的
type类型:
double--1
string--2
object--3
array--4
从集合中读取指定数量的数据记录:db.col.find().limit(number)
从集合中跳过指定数量的数据:db.col.find().limit(number).skip(number)
sort方法可以通过指定参数排序:db.col.find().sort({key:1}) 1代表升序,-1代表降序
4)limit skip sort 及数组中all in nin的用法
>db.person.find().count() 集合中数据的数量
>db.person.find({sex:{$type:1}},{_id:0,name:1}).limit(3) 只取三条数据
>db.person.find({sex:{$type:1}},{_id:0,name:1}).limit(3).skip(3) 跳过三条后再取三条
>db.person.find({},{_id:0,name:1,high:1}).sort({high:1}) 按身高升序排列
数组中关键字用法:
>db.person.find({hobby:{$all:["music"]}) 将爱好中包含音乐的人找出来
>db.person.find({hobby:{$in:["music","piano"]}) 只要满足其中一个即可
>db.person.find({hobby:{$nin:["music","piano"]}) 不在此范围
5)游标
>var x=db.col.find()
>x.hasNext()
>x.next()
6)循环插入数据,系统可以解析js脚本
>for(var i=0;i<10;i++){
db.person.insert({name:"zhangsan"+i,age:i})
}
6、文档更新
db.colName.update({查询条件},{更新内容} , 不存在时是否插入,更新第一个文档/更新所有文档)
0:不插入 0:更新第一个文档
1:插入 1:更新所有文档
文档全局替换:
>db.col.update({name:"zhangsan"},{age:30}) 将数据中的所有内容替换成age:30 只变更1条数据
局部更新:
>db.col.update({name:"lisi"},{$set:{age:32}}) 将数据中年龄字段值改成32 只变更1条数据
>db.col.update({name:"lisi"},{$set:{age:32}},0,1) 将所有lisi的年龄改成32
>db.col.update({name:"lisi"},{$set:{age:32}},1,1) 将所有lisi的年龄改成32,如果没有该数据先插入
>db.col.update({name:"lisi"},{$inc:{age:10}},0,1) 年龄增加10
>db.col.update({name:"lisi"},{$unset:{age:10}},0,1) 删除年龄字段
操作数组:
>db.col.update({name:"lisi"},{$set:{book:[]}},1,1) 增加一个空数组放书籍
>db.col.update({name:"lisi"},{$push:{book:["xiyouji"]}},1,1)
>db.col.update({name:"lisi"},{$pushAll:{book:["hongloumeng","sanguo","shuihu"]}},1,1)
>db.col.update({name:"lisi"},{$adToSet:{book:["shaonian"]}},1,1) 有则不添加,没有再添加
>db.col.update({name:"lisi"},{$pop:{book:1}},1,1) 删除数组中最后一个元素
>db.col.update({name:"lisi"},{$pop:{book:-1}},1,1) 删除数组中第一个元素
>db.col.update({name:"lisi"},{$pull:{book:"xiyouji"}},1,1) 删除数组中该元素
>db.col.update({name:"lisi"},{$pullAll:{book:"xiyouji","hongloumeng"}},1,1) 删除多个元素
7、索引
单字段索引:db.colName.ensureIndex({key:1})
key:创建索引的字段。1表示升序,-1表示降序
复合索引: db.colName.ensureIndex({key1:1,key2:1})
唯一索引: db.colName.ensureIndex({key1:1},{unique:true})
对比建索引前后效率提升:db.colName.find({name:"name200000"}).explain("executionStatus")
查询已经建立的索引:db.colName.getIndexs()
db.colName.status()
删除索引: db.colName.dropIndex({key:1})
8、分组
语法:db.colName.group(
{
key:{key1:1}, ----分组字段
cond{....}, ---查询条件,先根据该条件过滤。过滤后分组,对组内处理。
reduce:function(curr,result){....},
initial:{} ---初始化,分好组后开始执行该函数,执行完毕后调用reduce函数
finalize:function(result){} ---统计完一组后的回调函数
}
)
流程:根据查询条件过滤数据,分组,调用initial,调用reduce,调用finalize
数据库中插入一些数据用于测试:
> var student=[
{name:"zhangsan",gender:"m",high:178,class:"一(1)班",chinese:60,math:80,english:90},
{name:"lisi",gender:"w",high:160,class:"一(2)班",chinese:70,math:75,english:80},
{name:"wangwu",gender:"m",high:178,class:"三(1)班",chinese:85,math:65,english:95},
{name:"zhaoliu",gender:"w",high:178,class:"二(1)班",chinese:65,math:60,english:75},
.....
]
for(var i=0;i<student.length;i++){
db.student.insert(student[i]);
}
1)统计每个班的学生人数
>db.colName.group(
{
key:{class:1},
cond{},
reduce:function(curr,result){
result.count +=1;
},
initial:{count=0} ,
finalize:function(result){}
}
)
2)统计每个班男生人数
>db.colName.group(
{
key:{class:1},
cond{gender:"m"},
reduce:function(curr,result){
result.count +=1;
},
initial:{count=0},
finalize:function(result){}
}
)
3)统计出每个班身高总量
>db.colName.group(
{
key:{class:1},
cond{},
reduce:function(curr,result){
result.count +=curr.high;
},
initial:{count=0},
finalize:function(result){}
}
)
4)统计出每个班的平均身高
>db.colName.group(
{
key:{class:1},
cond{},
reduce:function(curr,result){
result.count +=1;
result.sum_high +=curr.high
},
initial:{count=0,sum_high=0},
finalize:function(result){}
result.avg_high=result.sum_high/result.count;
}
)
5)统计出每个班总分最高是多少
>db.colName.group(
{
key:{class:1},
cond{},
reduce:function(curr,result){
var currScore=curr.chinese+curr.english+curr.math;
if(result.maxScore <currScore){
result.maxScore=currScore;
}
},
initial:{maxScore=0}
)
注意:group不支持分布式运算,aggregate和mapreduce支持分布式
9、聚合操作
mongodb聚合aggregate 主要用于对集合中的数据进行各种统计,并返回统计后的数据结果
语法:db.colName.aggregate([{管道操作:{表达式}},........])
常用的管道操作:
$group:将集合中的文档分组,可用于统计结果
$math:用于过滤数据。只输出符合条件的文档,$math使用mongodb的标准查询操作
$project:修改输入文档的结构,可以用来重命名、增加、删除域。也用于创建计算结果及嵌套文档
$limit:用来限制聚合管道返回的文档数量
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档
$sort:将输入文档排序后输出
$unwind:将文档中某一个数组类型字段拆分成多条,每条包含数组中的一个值
聚合表达式:
$sum:求和
$avg:求平均数
$max:最大值
$min:最小值
$push:插入值到数组中
$first:获取第一个文档
$last:获取最后一个文档
数据库中插入一些数据用于测试:
> var persons=[
{name:"zhangsan",gender:"m",high:178,weight:75,salary:5800,hobby:["basketball","music","money"]},
{name:"lisi",gender:"m",high:180,weight:85,salary:6000,hobby:["run","piano","football"]},
{name:"wangwu",gender:"w",high:160,weight:55,salary:8000,hobby:["swimming","photo"]},
{name:"zhaoliu",gender:"w",high:170,weight:60,salary:5000,hobby:["writing","books","foods"]},
.....
]
for(var i=0;i<persons.length;i++){
db.persons.insert(persons[i]);
}
1)分别统计男女生人数
db.persons.aggregate([{$group:{_id:"gender",counter:{$sum:1}}}])
2)分别统计男女身高总数
db.persons.aggregate([{$group:{_id:"gender",counter:{$sum:"$high"}}}])
3)分别统计男女平均身高
db.persons.aggregate([{$group:{_id:"gender",avger:{$avg:"$high"}}}])
4)分别找出男女生第一个出现的人的身高
db.persons.aggregate([{$group:{_id:"gender",firster:{$first:"$high"}}}])
5)分别找出男女生最后一个出现的人的身高
db.persons.aggregate([{$group:{_id:"gender",laster:{$last:"$high"}}}])
6)分别找出男女生最高身高
db.persons.aggregate([{$group:{_id:"gender",maxer:{$max:"$high"}}}])
7)分别找出男女生最矮身高
db.persons.aggregate([{$group:{_id:"gender",miner:{$min:"$high"}}}])
8)按男女生分类将身高分别放到数组中
db.persons.aggregate([{$group:{_id:"gender",arr:{$push:"$high"}}}])
9)查询身高超过160的男女生人数----先过滤超过160的人,再分组
db.persons.aggregate([{$math:{high:{$gt:160}}},{$group:{_id:"gender",counter:{$sum:1}}}])
10)查询身高超过160的男女生人数,只输出人数 ----将id字段去掉
db.persons.aggregate([{$math:{high:{$gt:160}}},{$group:{_id:"gender",counter:{$sum:1}}},{$project:{_id:0,counter:1}}])
11)将男生女生的人数排序输出
db.persons.aggregate([{$math:{high:{$gt:160}}},{$group:{_id:"gender",counter:{$sum:1}}},{$sort:{counter:1}}])
12)对男生按身高排序输出第3到5名学生姓名和身高
db.persons.aggregate([{男性},{按身高排序},{跳过前两个},{取三条数据},{姓名和身高}])
db.persons.aggregate([{$math:{gender:"man"}},{$sort:{counter:1}},{$skip:2},{$limit:3},{$project:{_id:0,name:1,high:1}}])
13)对课程按组进行拆分---将一条数据拆分成多条
先在数据库中插数据:db.stus.insert({name:"xm",age:15,lesson:["语文","数学","英语"]})
db.stus.aggregate([{$unwind:"$lesson"}])