mongoDB基础应用

MongoDB 非关系型数据库

三,关系数据库的重要概念

1)关系模型:关系(二位表)来表达数据及数据之间的联系

2)实体:现实中可以区分的事物

3)属性:实体的属性特征

4)键(key):能够唯一区分某个实体的属性

4.1 主键 关系中逻辑上唯一区分一个实体的键(非空,唯一,不能重复)

5)索引:相当于字典的索引,提高查询效率的一种技术手段

通过避免全表扫描,会降低增删改的效率。索引会建立索引树

6)约束:数据必须遵循的规则

非空、唯一、默认值、自增长、外键

7)子查询:一个查询嵌套另一个查询

8)链接查询:从多个表查询,查询解雇是一个数据集(内连接,⬅左连接(左表为主表),有连接)

9)数据库事物:一组操作,或者多个操作。要么全都成功,要么全都不成功 (转账)

10)理论基础、框架、(树状结构、不知道为啥出来)

四,结构化数据和非结构化数据

1) 结构化数据
    
    整齐,规整
    每一笔数据具有相同的属性
    同一个属性类型,长度是一致的
    
2)非结构化数据
    
    不规则,没有预定的数据模型
    不方便使用二维表存储
    办公文档、网页、图片、视频、音频、文字

五,关系型的特点

1)优点
    
    结构概念简单,二位表来表示数据/数据联系
    数据一致性、完整性好
    技术成熟,有统一的标准
    
2)缺点
    
    1.性能瓶颈
    存在于硬盘上,几十M/s。大量IO操作,索引、外键 100万 *10万,表关联
    安全和速度是矛盾的
    2.扩展性差
    数据库服务器,水平扩展不好
    表达和存储非结构化数据的时候,不方便

六,非关系型数据库 (NoSql,Not only sql)

    1.什么是NoSql 数据不是存在二维表里面,数据存储不是采用二维表里
    2.树状结构,(不是简单的键值对,类似json文件)
      键值对 Redis
      列存储型 HBase
      文档型 MongoDB
      图型数据库
      
    3.非关系数据库特点
    高并发,读写能力强,低价值数据,一致性要求不高
    扩展性好,弱化了数据结构。
    
    缺点 通用性差,操作相对冗余,容易出错,容易混乱,联合查询、外键
    有的缺少join,事物等
    
    4.什么情况选择非NoSQL
    数据分析,人工智能
    对数据的一致性要求较低
    需要处理海量并发,要去高速读写
    作为临时数据存储的服务器
    方便构建非关系模型的时候
    
    web 开发java,php
    底层开发c,c++

七,MongoDB(非关系,文档型)

1.C++编写
2.支持丰富的增删改查
最像关系数据库的非关系数据库
3.支持丰富的编程语言类型
4.支持主流的编程语言接口
5.使用方便,便于扩展和部署
6.技术相对成熟

2.安装
Ubuntu 下自动安装
sudo apt-get install mongodb

重要的安装位置:/var/lib/mongodb
配置文件:/etc/mongodb.conf
命令集:/usr/bin 或者/usr/local/bin

brew services restart mongodb
mongo 即可访问mongoDB数据库

官网 www.mongodb.com

3.手动安装
下载包,采用相应的安装方式

添加环境变量

PATH=$PATH:/opt/mongodb/bin
export PATH

linux下
启动MongoDB: ./mongod --dbpath=/usr/mongo_data

4.查看服务
查看断开:netstat -an | grep 27017
通过脚本:/etc/init.d/mongodb status

MongoDB基本命令
启动并设置数据存储路径
1) mongod --dbpath 目录
   mongod --dbpath /var/mongo_data
   
2) 设置监听端口
   mongod --port 27019
   
3) 登录
登录通过Mongo shell

4) 退出 
exit、quit、ctrl + D

登录本地bank库
mongo 127.0.0.1:27017/bank 登录到bank库
   
登录到远程服务器某个库
mongo 192.168.1.5/bank -u xxx -p xxx

5) 查看服务状态
/etc/init.d/mongo [status|start|stop]

6)MongoDB数据库结构
键值对

关系-非关系数据库概念对照
名称      关系数据库       MongoDB
数据库     database        database
表         table           collection
行(记录)  row             document
列 (属性)  column          field
索引       index           index
主键       primary key     primary key 
    

MongoDB的操作
1.库操作

1)创建库:use databseName 切换进入某一个库
    说明:该库不存在,则会创建(实际使用时才会创建),写入数据才会真正创建.否则延迟加载
    类似于函数调用,写入数据
    db.acct.insert({name:"Jerry"})
    db.dropDatabase() 删表,一定要备份
    show collections 查看数据库里面的表
    db.表名.find() 查询表里的数据
    
2) 查看库:show dbs;
    admin:内置库,管理员用户库
    local: 存放本地服务器的信息,该库的内容不会放在服务器分片之间进行复制
    config:保存分片信息
    
3) 库命名的规则
    默认使用utf-8
    库名称不能有空格,点,/ ,\,'\0' 表示字符串的结束
    
    长度不超过64个字节
    不能系统库重名
    
4) 删除库
   db.dropDatabase()

2.数据库的备份和恢复
ls /opt/mongodb
mongodump
mongorestore
linux下不需要登录

mongodump -h 主机 -d 库名 -o 目录
mongodump -h localhost -d bank -o ./databank
mac 下使用这个命令备份库
mongodump -h localhost -d bank -o ~/Desktop/databank/

恢复:mongorstore -h 主机:端口 -d 库名 目录
e.g
从./databank/bank 目录恢复bank库的数据

mongorestore -h localhost:27017 -d bank ./databank/bank/
mongorestore -h localhost:27017 -d bank ~/Desktop/databank/bank/

数据库检测: mongostat
insert,query,update,delete 每秒执行的次数

flushes :每秒刷新缓存的次数
vsize: 虚拟内存的使用量
res: 物理内存的使用量

检测读写时长
mongotop
total 总时长
read 读时长
write 写时长

五,集合的概念和操作

   什么是集合
   1.文档组,对应关系数据库中表的概念
   
   2.集合没有特定的数据结构
   每条数据可能包含不通的域,每个同名称的域可能类型不一样
   
   3.当在集合在插入数据时,集合被自动创建
   域一样,对于增删改有好处
   一个集合存放一类数据,数据太乱。程序操作比较困难
   
   4.集合创建
   db.createCollection(name)
   db.tmp.insert({name:"jerry"}) 直接插入数据,集合自动创建
   
   集合命名规范 
   不能使用空字符串
   不能含有'\0'
   不能以system.开头,这是系统保留集合前缀
   不能含有包留字符,不能包含'$'
   
   5.删除集合和重命名
   1) 删除 db.collectionName.drop()
       db.cust.drop()
   2) 重命名 
      db.collectionNmae.renameCollection(新名称)
      db.cust.renameCollection(customer)

文档操作,(数据),重点

1)构成集合的基本单位,一条记录
一个文档存储1笔数据(对应行)

{
    键值对
    key : "Value"
}
  1. mongoDB键值对是有序的
    mongoDB中大小写敏感
    mongoDB中不能有重复的key
    mongoDB中key的要求必须是utf-8

json 可读性好
真正存的时候是二进制格式,BSON(Binary JSON),节约存储空间
mongoDB存储文档的一种格式

存储效率高,可读性好,轻量级等优点

db.acct.insert({
    acct_no:"6223450001",
    acct_name:"Jerry",
    acct_type:1,
    balance:1234.56,
})

查询所有文档,格式化一下

db.acct.find().pretty()
db.acct.find({条件1,条件2..})

物理上多台服务器,但逻辑上要看做1天服务器

db.acct.find({条件,设置显示的域})
db.acct.find({},{id:0}) # 0 不显示id域 1 显示

删除
db.acct.remove()

容易出错的地方:
不好不正确匹配或嵌套不正确
英文符号写成中文

_id : + 进程id + 流水号

插入多笔数据

db.acct.insert([{
    
},{

}])

save插入,支持更新

db.acct.save({
    name:"Jerry",
    acct_type:"2",
})

objectId:系统产生的主键,名称固定,——id自己可以填写该值,保证唯一性
24位十六进制
8位文档创建时间
6位 机器id
4位 进程id
6位 流水号

MongoDB支持的数据类型
Double 1
String 2
Object 3 内嵌文档
Array 4 一组数据
BinaryData 5
ObjectId 7
Boolean 8
Date 9 日期时间类型
NULL 10
regex 10
code 15
integer 16/18
TimeStamp

创建一个订单 orders
order_id:订单编号,字符串
cust_name 客户名称,字符串
order_data 下单时间,Date类型 new Date()
status:订单状态,整数
order_detail:订单明细
product_id:
product_name:
amt:

在orders表中插入3条订单数据
至少有1个订单
没个订单至少包含多件商品

mongodb中的比较操作符号

 $eq/$ne,ne不等于
 dc.acct.find({
     acct_type:{$ne:1}
 })

大于: $gt greater than

db.acct.find({
     balane:{$gt:5000}
})

大于等于 gte 小于等于lte

包含/不包含
in,nin

$and 逻辑且

db.acct.find({
  acct_no:"63180198301",
  acct_name:"Jerry"
})

db.acct.find({
  $and:[
          {acct_no:"3019810"},
          {acct_no:"1097091"}
      ]    
})

$or 逻辑或

db.acct.find({
  $or:[
      {
      },
      {
      }
  ]
})

$not用法

db.acct.find({
      acct_ype:{$not:{$eq:1}}
})

$nor 既不是也不是,表示两个否定的条件

db.acct.find({
  $nor: [
      {acct_type:3},
      {balance:2000},
  ]
})

构建一个带有数组的集合

db.student.insert({
  name:"Dake",
  age:22,
  score:[60,70,80]
})

查询:

db.student.find({
  score:70
})

db.student.find({
  score:{$all:[70,90]}
})

size 为3.只有三门成绩

db.student.find({
  score:{$size:3}
})

其他查询指令 exists
判断是否存在某个域

db.student.find({
  sex:{$exists:true}
})

$exists false 择查找sex 域不存在的数据

根据余数查找 $mod,查找年龄为奇数的学生信息

db.student.find({
  age:{$mod:[2,1]}
})

查找函数:去重。显示前N笔,排序,统计
distinct:去重,需要排序

db.acct.distinct("acct_type")

limit: 显示查找结果的前N笔
db.student.find().limit(2)

跳过找找结果前N笔

db.acct.find.skip(2)
db.acct.find({acct_type:1}).count()

sort 1 升序 -1 降序

db.acct.find().sort({balance:-1})

文档删除

db.集合名称.remove(query,justone)
说明:query,筛选条件,如果写作,表示删除所有

query,删除谁有
justone:true 删除一笔符合条件的
false:删除所有符合条件的

db.acct.remove({
  acct_type:3
},true) 

修改文档
db.集合名称.update(query,update,upsert,mulit)
说明: query 筛选条件,格式和写法通查询操作
update 修改内容
upsert 让他如果没有满足条件时,是否执行插入 true是 false 否
multi 是否修改多笔

set 修改域的值
修改某个账户的余额

db.acct.update({
  {acct_no:"2222"},
  {set:{balance:0.00,close_date:new Date()}
  },
  false,
  false,
})

$rename 修改域名称

db.acct.update({
  {acct_no:"2222"},
  {$rename:
      {"close_date","revoke_data"
      }
  },
  false,
  false,
})

$inc : 加法修改器 完成域的加减运算
e.g. 将某个账户余额增加10000(例如存款)

db.acct.update({
  {acct_no:"11231313"}
  {$inc:{balance:10000}},
  false,
  false
})

$mul 乘法修改器
e.g 将某个账户余额增加2%的利息

 db.student.update({
  {acct_no:"11231313"}
  {$mul:{balance:1.02}},
  false,
  false
})

$min 用指定的值,取小值

db.course_score.insert(name:"bob",score:104)
db.course_score.insert(name:"Tom",score:92)
db.course_score.insert(name:"Alice",score:80)

db.student.update({
  {}
  {$min:{score:100}},
  false,
  false
})

$max 用指定的值和某个值比较取其中较大的值
e.g. 取低于45的成绩修改成45分

db.student.update({
  {}
  {$max:{score:45}},
  false,
  true
})

push/pushAll 向数组中添加一项或者多项数据
e.g. 向students集合中,名称为David的一门成绩

db.student.update({
  {name:"David"},
  {$push:{score:00}},
  false,
  true,
})

db.student.update({
  {name:"David"},
  {$pushAll:{score:[88,77]}},
  false,
  true,
})

pull/pullAll 向数组中删除一项/多项值
e.g. 删除集合中,名称为Dokie的77分成绩

db.student.update({
  {name:"Dekie"},
  {pull:{score:77}},
  false,
  true,
})

查找 status 为1的数据

db.orders.find({
  status:1
})


db.orders.find({status:{$ne:1}})

db.orders.insert({
  order_id:"2010729183",
  cust_name:"Tome",
  order_date:new Date(),
  status:2,
  order_detail:[
      {
          "product_id":"P0003",
          "product_name":"棉花",
          "amt": 1,
          "price":88,
      },
  ]
})

查询所有订单,不显示_id域

db.orders.find({
  {},
  {_id:0}
})

查询状态在[1,3,4]中的订单

db.orders.find({
  status:{
      $in:[1,3,4]
  }
})

查询所有包含两件商品的订单,判断元的个数

db.orders.find({
  order_detail:{$size:2}
})

某个时间点以后的订单

db.orders.find({
  order_date:{$gt:ISODate("2019-01-20T02:12:37.937Z")}
})

数组操作
将值插入数组某个指定的位置

需要push,each配合使用
e.g 将99,100两门成绩,插入Dekie学生的成绩的第一,第二个位置

db.student.update(
  {name:"Dekie"},
  {$push:{score:{$each:[100],$postion:0}}}
)

插入两门成绩,放在第二个位置

db.student.update(
  {name:"Dekie"},
  {$push:{score:{$each:[33,44],$postion:1}}}
)

2.弹出数组中的一项
$pop,弹出数组中的一项

db.student.update(
    {
      name:"Dekie",  
    },
    {
      $pop:{
          score:1
      }
    }
)

$addToSet: 向数组中添加一项,并去重

db.student.update(
  {name:"Dekie",},
  {$addToSet: {
      score:33,
  }
)

$使用数组的索引查找
e.g 找student集合中,第一项成绩为33数据

db.student.find({
  "score.0":33
})

2.其他数据类型

1)日期时间类型 记录整数,表示自1970-01-01 00:00:00 到当前时间的毫秒数
2) 取得日期时间 Date()

插入一条数据

db.tim_test.insert(
  {
      date1:Date(),date2:new Date()
  }
)

3).将ISODate转换为本地时间
ISODate().toLocaleString()

4).用指定的时间去创建对象

new Date("2018-01-01T18:02:54")
  
db.time_test.insert(
  {
      date1:new Date("2018-01-01T18:02:54"),
  }
)

NULL 类型,键/值、域不存在,未设置值
e.g. 查询某个域为空

db.acct.find(
  {reg_date:null}
)

判断有没有这个域

db.acct.find({reg_date:{$exists:true}})

查找某个域为空的数据
revoke_date

db.acct.find(
  {
      reg_date:null
  }
)

4.内嵌文档 (重点)

文档中某个值还是文档
示例见
e.g 创建含有内嵌文档的集合

db.cust_info.insert({
  cust_id:"0002",
  cust_name:"Tom",
  contact:{
      tel:"18510780940",
      email:"919938027@qq.com",   
      address:"beijing"     
  }
})

查找内嵌文档中的某个数据

db.cust_info.find(
  {
      "contact.tel":"13107716356",
  }
)

修改内嵌文档中某个数据

db.cust_info.update(
    {
      cust_id:"0001"
    },
    {
      $set:{"contact.tel":"13811112222"}
    }
)

5.索引
MyISam 二级索引
大部分数据排除掉

增删改,都会去调整索引。索引要建立在关键的字段
索引,数据量分布要均匀。

1.什么是索引
指定键值及其文档所在位置的关系对照清单

2.用途
通过索引,快速定位文档的位置。通过避免全表扫描的,提高检索效率

3.索引的开销
数据增删改,会调整索引结构。牺牲部分增删改的效率,来提升查询效率
会有额外的存储空间
索引使用的注意事项 (建立适合的索引)
索引不宜太多
数据太少不适合创建索引

在域上创建索引
语法:
db.集合名称.createIndex(域,类型)
类型 1 升序 - 1降序
示例见:在acct集合acct_name创建索引

  db.acct.createIndex(
      {   
          acct_name:1
      }
  )

查看索引
db.集合名称.getIndexes()

删除索引
db.集合名称.dropIndex(索引名称)

删除某个集合的索引
db.acct.dropIndex(""acct_name_1")

索引类型
复合索引:多个域创建索引
e.g 在acct集合的acct_name创建升序,reg_date域创建降序索引

db.acct.createIndex(
  {
      acct_name:1,
      reg_date:-1,
  }
)

唯一索引,域的值不能重复
指定unique为true来创建唯一索引

e.g. 在acct集合的acct_no域创建唯一索引

db.acct.createIndex(
  {
      acct_no:1
  },
  {
      unique:true
  }
)

插入一笔存在的账户数据,验证

db.acct.insert(
  {
      acct_no:
  }
)

稀疏索引:(间隙索引)如果域不存在,择不该文档进行索引,从而提高索引的效率
通过指定sparse为true,来创建稀疏索引
e.g. 在cust_info集合fax域创建稀疏索引

db.cust_info.createIndex(
  {
      fax:1,
  },
  {
      sparse:true
  }
) 

6.聚合操作

1)聚合:对文档进行高级筛选,主要用于统计,求平均,求和等等
2)聚合函数:
    db.集合名称.aggregate()
    功能:完成聚合操作
    参数:聚合条件,配合聚合操作符
    返回:返回聚合的结果
    
3)常用聚合
分组:$group(需要和统计操作配合使用)
e.g 分组统计

acct_type 统计各类账户的数量

 db.acct.aggregate(
   {
      $group: {
          '_id':'$acct_type',
          num:{$sum:1}
      }    
   }
 )
 

类似于sql:
select acct_type,count(*) from acct group by acct_type
注意:在统计笔数时候,num后面只能是1,分组域前面的符号不能少

对某个域求和
e.g 分组统计各类账户余额的总和

db.acct.aggregate(
  {
      $group: {
          '_id':'acct_type',
          total:{
              $sum:'$balance',
          }
      }
  }
)

聚合操作

  1. $max : 求最大值
    e.g. 找出各类账户中余额最大的值
db.acct.aggregate(
  {
      $group: {
          '_id':'acct_type',
          max_value:{
              $max:'$balance'
          }
      }
  }
)

  1. $min: 求最小值
db.acct.aggregate(
  {
      $group: {
          '_id':'acct_type',
          min_value:{
              $min:'balance',
          }
      }
  }
)

  1. $avg:求平均值
db.acct.aggregate(
  {
      $group: {
          '_id':'acct_type',
          avg_value:{
              $avg:'balance',
          }
      }
  }
) 
    
  1. $project:集合中查询指定的域
    类似于sql的投影运算
    e.g. 现在从acct集合中查询账户和户名。
  db.acct.aggregate(
      {
          _id:0,
          '账号':'$acct_no',
          '户名':'$acct_name'
      }
  )
  

类似于 select acct_no as "账号", acct_name as "户名" from acct
在mongo里面称为投影聚合

5) $match: 对账号数据进行过滤
e.g. 查询账户余额小于5000的账号

db.acct.aggregate(
  {
      $match:{
          balance:{
              $lt:5000
          }
      }
  }
)

6)$sort :排序
查询所有账号数据

db.acct.aggregate(
  {
      $sort: {
          balance:-1
      }
  }
)

-1 表示降序, 1表示升序

7)管道聚合:上一个操作完成后,将结果作为下一个操作的输入
e.g. 对acct集合根据acct_type进行筛选,然后对筛选结果按照账户进行降序排序

db.acct.aggrgate(
   {
      $match:{
          acct_type:1
      },
   },
   {
      $sort:{
          acct_no:-1
      }
   }    
)

  1. 固定集合 (Capped Collections)
  1) 什么是固定集合
  - 有固定大小的集合(存储空间,笔数)
  - 当数据大小/笔数超过上限后
  再插入新的数据会覆盖初始头部的数据
  
  - 优点:
    插入速度快,顺序查找快
    能够淘汰早期数据
    控制集合大小
    应用场景
    日志
    临时缓存
            

如何创建固定集合:

-语法:

db.createCollection(
  {
     集合名称,
     {
         capped:true,
         size:10000,
         max:100
     }
  }
)

capped: 设置为true,表示创建固定集合
size:集合的大小,单位bytes max:最多存放多少个文档
e.g. 创建集合log,限定最多存储3笔数据

db.createCollection(
  {
      'log',
      {
          capped:true,
          size:10000,
          max:3,
      }
  }
)

插入数据,第4笔就会覆盖前面的数据

db.log.insert(
  {
      name:"Jerry",
      oper:'delete',
  }
)

db.log.insert(
  {
      name:"Tom",
      oper:'delete',
  }
)

db.log.insert(
  {
      name:"Tom",
      oper:'delete',
  }
)

课堂练习

1)统计订单笔数
db.orders.find().count()

2)查询所有订单,按照下单时间倒叙显示

db.orders.find().sort({order_date:-1}).pretty()

3)修改某个订单的状态

db.orders.update(
  {
      {order_id:"201801010101"},
      {set:{
              status:2,
           }
      },
      false,
      false,
  }
)

4)为所有订单添加一个状态,支付状态 payment_status
5)查询所有订单中,包含了编号为"P0001"商品的订单
6)在订单集合的订单编号(order_id)域创建升序所有
7)为某个订单添加备注信息(要求为字符串数组)
8)删除一笔无效订单,(订单状态删除,值自定)

db.orders.insert(
  {
      order_id:"2411673791",
      cust_name:"baiyanfeng",
      order_date:new Date(),
      payment_status:0,
      order_detail:[
          {
              product_id:"P0026",
              product_name:"js",
              amt:1,
              price:202151,
          }
      ]
  }
)
# MongoDB 非关系型数据库

三,关系数据库的重要概念

1)关系模型:关系(二位表)来表达数据及数据之间的联系

2)实体:现实中可以区分的事物

3)属性:实体的属性特征

4)键(key):能够唯一区分某个实体的属性

4.1 主键 关系中逻辑上唯一区分一个实体的键(非空,唯一,不能重复)

5)索引:相当于字典的索引,提高查询效率的一种技术手段

通过避免全表扫描,会降低增删改的效率。索引会建立索引树

6)约束:数据必须遵循的规则

非空、唯一、默认值、自增长、外键

7)子查询:一个查询嵌套另一个查询

8)链接查询:从多个表查询,查询解雇是一个数据集(内连接,⬅左连接(左表为主表),有连接)

9)数据库事物:一组操作,或者多个操作。要么全都成功,要么全都不成功 (转账)

10)理论基础、框架、(树状结构、不知道为啥出来)

四,结构化数据和非结构化数据

1) 结构化数据
    
    整齐,规整
    每一笔数据具有相同的属性
    同一个属性类型,长度是一致的
    
2)非结构化数据
    
    不规则,没有预定的数据模型
    不方便使用二维表存储
    办公文档、网页、图片、视频、音频、文字

五,关系型的特点

1)优点
    
    结构概念简单,二位表来表示数据/数据联系
    数据一致性、完整性好
    技术成熟,有统一的标准
    
2)缺点
    
    1.性能瓶颈
    存在于硬盘上,几十M/s。大量IO操作,索引、外键 100万 *10万,表关联
    安全和速度是矛盾的
    2.扩展性差
    数据库服务器,水平扩展不好
    表达和存储非结构化数据的时候,不方便

六,非关系型数据库 (NoSql,Not only sql)

    1.什么是NoSql 数据不是存在二维表里面,数据存储不是采用二维表里
    2.树状结构,(不是简单的键值对,类似json文件)
      键值对 Redis
      列存储型 HBase
      文档型 MongoDB
      图型数据库
      
    3.非关系数据库特点
    高并发,读写能力强,低价值数据,一致性要求不高
    扩展性好,弱化了数据结构。
    
    缺点 通用性差,操作相对冗余,容易出错,容易混乱,联合查询、外键
    有的缺少join,事物等
    
    4.什么情况选择非NoSQL
    数据分析,人工智能
    对数据的一致性要求较低
    需要处理海量并发,要去高速读写
    作为临时数据存储的服务器
    方便构建非关系模型的时候
    
    web 开发java,php
    底层开发c,c++

七,MongoDB(非关系,文档型)

1.C++编写
2.支持丰富的增删改查
最像关系数据库的非关系数据库
3.支持丰富的编程语言类型
4.支持主流的编程语言接口
5.使用方便,便于扩展和部署
6.技术相对成熟

2.安装
Ubuntu 下自动安装
sudo apt-get install mongodb

重要的安装位置:/var/lib/mongodb
配置文件:/etc/mongodb.conf
命令集:/usr/bin 或者/usr/local/bin

brew services restart mongodb
mongo 即可访问mongoDB数据库

官网 www.mongodb.com

3.手动安装
下载包,采用相应的安装方式

添加环境变量

PATH=$PATH:/opt/mongodb/bin
export PATH

linux下
启动MongoDB: ./mongod --dbpath=/usr/mongo_data

4.查看服务
查看断开:netstat -an | grep 27017
通过脚本:/etc/init.d/mongodb status

MongoDB基本命令
启动并设置数据存储路径
1) mongod --dbpath 目录
   mongod --dbpath /var/mongo_data
   
2) 设置监听端口
   mongod --port 27019
   
3) 登录
登录通过Mongo shell

4) 退出 
exit、quit、ctrl + D

登录本地bank库
mongo 127.0.0.1:27017/bank 登录到bank库
   
登录到远程服务器某个库
mongo 192.168.1.5/bank -u xxx -p xxx

5) 查看服务状态
/etc/init.d/mongo [status|start|stop]

6)MongoDB数据库结构
键值对

关系-非关系数据库概念对照
名称      关系数据库       MongoDB
数据库     database        database
表         table           collection
行(记录)  row             document
列 (属性)  column          field
索引       index           index
主键       primary key     primary key 
    

MongoDB的操作
1.库操作

1)创建库:use databseName 切换进入某一个库
    说明:该库不存在,则会创建(实际使用时才会创建),写入数据才会真正创建.否则延迟加载
    类似于函数调用,写入数据
    db.acct.insert({name:"Jerry"})
    db.dropDatabase() 删表,一定要备份
    show collections 查看数据库里面的表
    db.表名.find() 查询表里的数据
    
2) 查看库:show dbs;
    admin:内置库,管理员用户库
    local: 存放本地服务器的信息,该库的内容不会放在服务器分片之间进行复制
    config:保存分片信息
    
3) 库命名的规则
    默认使用utf-8
    库名称不能有空格,点,/ ,\,'\0' 表示字符串的结束
    
    长度不超过64个字节
    不能系统库重名
    
4) 删除库
   db.dropDatabase()

2.数据库的备份和恢复
ls /opt/mongodb
mongodump
mongorestore
linux下不需要登录

mongodump -h 主机 -d 库名 -o 目录
mongodump -h localhost -d bank -o ./databank
mac 下使用这个命令备份库
mongodump -h localhost -d bank -o ~/Desktop/databank/

恢复:mongorstore -h 主机:端口 -d 库名 目录
e.g
从./databank/bank 目录恢复bank库的数据

mongorestore -h localhost:27017 -d bank ./databank/bank/
mongorestore -h localhost:27017 -d bank ~/Desktop/databank/bank/

数据库检测: mongostat
insert,query,update,delete 每秒执行的次数

flushes :每秒刷新缓存的次数
vsize: 虚拟内存的使用量
res: 物理内存的使用量

检测读写时长
mongotop
total 总时长
read 读时长
write 写时长

五,集合的概念和操作

   什么是集合
   1.文档组,对应关系数据库中表的概念
   
   2.集合没有特定的数据结构
   每条数据可能包含不通的域,每个同名称的域可能类型不一样
   
   3.当在集合在插入数据时,集合被自动创建
   域一样,对于增删改有好处
   一个集合存放一类数据,数据太乱。程序操作比较困难
   
   4.集合创建
   db.createCollection(name)
   db.tmp.insert({name:"jerry"}) 直接插入数据,集合自动创建
   
   集合命名规范 
   不能使用空字符串
   不能含有'\0'
   不能以system.开头,这是系统保留集合前缀
   不能含有包留字符,不能包含'$'
   
   5.删除集合和重命名
   1) 删除 db.collectionName.drop()
       db.cust.drop()
   2) 重命名 
      db.collectionNmae.renameCollection(新名称)
      db.cust.renameCollection(customer)

文档操作,(数据),重点

1)构成集合的基本单位,一条记录
一个文档存储1笔数据(对应行)

{
    键值对
    key : "Value"
}
  1. mongoDB键值对是有序的
    mongoDB中大小写敏感
    mongoDB中不能有重复的key
    mongoDB中key的要求必须是utf-8

json 可读性好
真正存的时候是二进制格式,BSON(Binary JSON),节约存储空间
mongoDB存储文档的一种格式

存储效率高,可读性好,轻量级等优点

db.acct.insert({
    acct_no:"6223450001",
    acct_name:"Jerry",
    acct_type:1,
    balance:1234.56,
})

查询所有文档,格式化一下

db.acct.find().pretty()
db.acct.find({条件1,条件2..})

物理上多台服务器,但逻辑上要看做1天服务器

db.acct.find({条件,设置显示的域})
db.acct.find({},{id:0}) # 0 不显示id域 1 显示

删除
db.acct.remove()

容易出错的地方:
不好不正确匹配或嵌套不正确
英文符号写成中文

_id : + 进程id + 流水号

插入多笔数据

db.acct.insert([{
    
},{

}])

save插入,支持更新

db.acct.save({
    name:"Jerry",
    acct_type:"2",
})

objectId:系统产生的主键,名称固定,——id自己可以填写该值,保证唯一性
24位十六进制
8位文档创建时间
6位 机器id
4位 进程id
6位 流水号

MongoDB支持的数据类型
Double 1
String 2
Object 3 内嵌文档
Array 4 一组数据
BinaryData 5
ObjectId 7
Boolean 8
Date 9 日期时间类型
NULL 10
regex 10
code 15
integer 16/18
TimeStamp

创建一个订单 orders
order_id:订单编号,字符串
cust_name 客户名称,字符串
order_data 下单时间,Date类型 new Date()
status:订单状态,整数
order_detail:订单明细
product_id:
product_name:
amt:

在orders表中插入3条订单数据
至少有1个订单
没个订单至少包含多件商品

mongodb中的比较操作符号

 $eq/$ne,ne不等于
 dc.acct.find({
     acct_type:{$ne:1}
 })

大于: $gt greater than

db.acct.find({
     balane:{$gt:5000}
})

大于等于 gte 小于等于lte

包含/不包含
in,nin

$and 逻辑且

db.acct.find({
  acct_no:"63180198301",
  acct_name:"Jerry"
})

db.acct.find({
  $and:[
          {acct_no:"3019810"},
          {acct_no:"1097091"}
      ]    
})

$or 逻辑或

db.acct.find({
  $or:[
      {
      },
      {
      }
  ]
})

$not用法

db.acct.find({
      acct_ype:{$not:{$eq:1}}
})

$nor 既不是也不是,表示两个否定的条件

db.acct.find({
  $nor: [
      {acct_type:3},
      {balance:2000},
  ]
})

构建一个带有数组的集合

db.student.insert({
  name:"Dake",
  age:22,
  score:[60,70,80]
})

查询:

db.student.find({
  score:70
})

db.student.find({
  score:{$all:[70,90]}
})

size 为3.只有三门成绩

db.student.find({
  score:{$size:3}
})

其他查询指令 exists
判断是否存在某个域

db.student.find({
  sex:{$exists:true}
})

$exists false 择查找sex 域不存在的数据

根据余数查找 $mod,查找年龄为奇数的学生信息

db.student.find({
  age:{$mod:[2,1]}
})

查找函数:去重。显示前N笔,排序,统计
distinct:去重,需要排序

db.acct.distinct("acct_type")

limit: 显示查找结果的前N笔
db.student.find().limit(2)

跳过找找结果前N笔

db.acct.find.skip(2)
db.acct.find({acct_type:1}).count()

sort 1 升序 -1 降序

db.acct.find().sort({balance:-1})

文档删除

db.集合名称.remove(query,justone)
说明:query,筛选条件,如果写作,表示删除所有

query,删除谁有
justone:true 删除一笔符合条件的
false:删除所有符合条件的

db.acct.remove({
  acct_type:3
},true) 

修改文档
db.集合名称.update(query,update,upsert,mulit)
说明: query 筛选条件,格式和写法通查询操作
update 修改内容
upsert 让他如果没有满足条件时,是否执行插入 true是 false 否
multi 是否修改多笔

set 修改域的值
修改某个账户的余额

db.acct.update({
  {acct_no:"2222"},
  {set:{balance:0.00,close_date:new Date()}
  },
  false,
  false,
})

$rename 修改域名称

db.acct.update({
  {acct_no:"2222"},
  {$rename:
      {"close_date","revoke_data"
      }
  },
  false,
  false,
})

$inc : 加法修改器 完成域的加减运算
e.g. 将某个账户余额增加10000(例如存款)

db.acct.update({
  {acct_no:"11231313"}
  {$inc:{balance:10000}},
  false,
  false
})

$mul 乘法修改器
e.g 将某个账户余额增加2%的利息

 db.student.update({
  {acct_no:"11231313"}
  {$mul:{balance:1.02}},
  false,
  false
})

$min 用指定的值,取小值

db.course_score.insert(name:"bob",score:104)
db.course_score.insert(name:"Tom",score:92)
db.course_score.insert(name:"Alice",score:80)

db.student.update({
  {}
  {$min:{score:100}},
  false,
  false
})

$max 用指定的值和某个值比较取其中较大的值
e.g. 取低于45的成绩修改成45分

db.student.update({
  {}
  {$max:{score:45}},
  false,
  true
})

push/pushAll 向数组中添加一项或者多项数据
e.g. 向students集合中,名称为David的一门成绩

db.student.update({
  {name:"David"},
  {$push:{score:00}},
  false,
  true,
})

db.student.update({
  {name:"David"},
  {$pushAll:{score:[88,77]}},
  false,
  true,
})

pull/pullAll 向数组中删除一项/多项值
e.g. 删除集合中,名称为Dokie的77分成绩

db.student.update({
  {name:"Dekie"},
  {pull:{score:77}},
  false,
  true,
})

查找 status 为1的数据

db.orders.find({
  status:1
})


db.orders.find({status:{$ne:1}})

db.orders.insert({
  order_id:"2010729183",
  cust_name:"Tome",
  order_date:new Date(),
  status:2,
  order_detail:[
      {
          "product_id":"P0003",
          "product_name":"棉花",
          "amt": 1,
          "price":88,
      },
  ]
})

查询所有订单,不显示_id域

db.orders.find({
  {},
  {_id:0}
})

查询状态在[1,3,4]中的订单

db.orders.find({
  status:{
      $in:[1,3,4]
  }
})

查询所有包含两件商品的订单,判断元的个数

db.orders.find({
  order_detail:{$size:2}
})

某个时间点以后的订单

db.orders.find({
  order_date:{$gt:ISODate("2019-01-20T02:12:37.937Z")}
})

数组操作
将值插入数组某个指定的位置

需要push,each配合使用
e.g 将99,100两门成绩,插入Dekie学生的成绩的第一,第二个位置

db.student.update(
  {name:"Dekie"},
  {$push:{score:{$each:[100],$postion:0}}}
)

插入两门成绩,放在第二个位置

db.student.update(
  {name:"Dekie"},
  {$push:{score:{$each:[33,44],$postion:1}}}
)

2.弹出数组中的一项
$pop,弹出数组中的一项

db.student.update(
    {
      name:"Dekie",  
    },
    {
      $pop:{
          score:1
      }
    }
)

$addToSet: 向数组中添加一项,并去重

db.student.update(
  {name:"Dekie",},
  {$addToSet: {
      score:33,
  }
)

$使用数组的索引查找
e.g 找student集合中,第一项成绩为33数据

db.student.find({
  "score.0":33
})

2.其他数据类型

1)日期时间类型 记录整数,表示自1970-01-01 00:00:00 到当前时间的毫秒数
2) 取得日期时间 Date()

插入一条数据

db.tim_test.insert(
  {
      date1:Date(),date2:new Date()
  }
)

3).将ISODate转换为本地时间
ISODate().toLocaleString()

4).用指定的时间去创建对象

new Date("2018-01-01T18:02:54")
  
db.time_test.insert(
  {
      date1:new Date("2018-01-01T18:02:54"),
  }
)

NULL 类型,键/值、域不存在,未设置值
e.g. 查询某个域为空

db.acct.find(
  {reg_date:null}
)

判断有没有这个域

db.acct.find({reg_date:{$exists:true}})

查找某个域为空的数据
revoke_date

db.acct.find(
  {
      reg_date:null
  }
)

4.内嵌文档 (重点)

文档中某个值还是文档
示例见
e.g 创建含有内嵌文档的集合

db.cust_info.insert({
  cust_id:"0002",
  cust_name:"Tom",
  contact:{
      tel:"18510780940",
      email:"919938027@qq.com",   
      address:"beijing"     
  }
})

查找内嵌文档中的某个数据

db.cust_info.find(
  {
      "contact.tel":"13107716356",
  }
)

修改内嵌文档中某个数据

db.cust_info.update(
    {
      cust_id:"0001"
    },
    {
      $set:{"contact.tel":"13811112222"}
    }
)

5.索引
MyISam 二级索引
大部分数据排除掉

增删改,都会去调整索引。索引要建立在关键的字段
索引,数据量分布要均匀。

1.什么是索引
指定键值及其文档所在位置的关系对照清单

2.用途
通过索引,快速定位文档的位置。通过避免全表扫描的,提高检索效率

3.索引的开销
数据增删改,会调整索引结构。牺牲部分增删改的效率,来提升查询效率
会有额外的存储空间
索引使用的注意事项 (建立适合的索引)
索引不宜太多
数据太少不适合创建索引

在域上创建索引
语法:
db.集合名称.createIndex(域,类型)
类型 1 升序 - 1降序
示例见:在acct集合acct_name创建索引

  db.acct.createIndex(
      {   
          acct_name:1
      }
  )

查看索引
db.集合名称.getIndexes()

删除索引
db.集合名称.dropIndex(索引名称)

删除某个集合的索引
db.acct.dropIndex(""acct_name_1")

索引类型
复合索引:多个域创建索引
e.g 在acct集合的acct_name创建升序,reg_date域创建降序索引

db.acct.createIndex(
  {
      acct_name:1,
      reg_date:-1,
  }
)

唯一索引,域的值不能重复
指定unique为true来创建唯一索引

e.g. 在acct集合的acct_no域创建唯一索引

db.acct.createIndex(
  {
      acct_no:1
  },
  {
      unique:true
  }
)

插入一笔存在的账户数据,验证

db.acct.insert(
  {
      acct_no:
  }
)

稀疏索引:(间隙索引)如果域不存在,择不该文档进行索引,从而提高索引的效率
通过指定sparse为true,来创建稀疏索引
e.g. 在cust_info集合fax域创建稀疏索引

db.cust_info.createIndex(
  {
      fax:1,
  },
  {
      sparse:true
  }
) 

6.聚合操作

1)聚合:对文档进行高级筛选,主要用于统计,求平均,求和等等
2)聚合函数:
    db.集合名称.aggregate()
    功能:完成聚合操作
    参数:聚合条件,配合聚合操作符
    返回:返回聚合的结果
    
3)常用聚合
分组:$group(需要和统计操作配合使用)
e.g 分组统计

acct_type 统计各类账户的数量

 db.acct.aggregate(
   {
      $group: {
          '_id':'$acct_type',
          num:{$sum:1}
      }    
   }
 )
 

类似于sql:
select acct_type,count(*) from acct group by acct_type
注意:在统计笔数时候,num后面只能是1,分组域前面的符号不能少

对某个域求和
e.g 分组统计各类账户余额的总和

db.acct.aggregate(
  {
      $group: {
          '_id':'acct_type',
          total:{
              $sum:'$balance',
          }
      }
  }
)

聚合操作

  1. $max : 求最大值
    e.g. 找出各类账户中余额最大的值
db.acct.aggregate(
  {
      $group: {
          '_id':'acct_type',
          max_value:{
              $max:'$balance'
          }
      }
  }
)

  1. $min: 求最小值
db.acct.aggregate(
  {
      $group: {
          '_id':'acct_type',
          min_value:{
              $min:'balance',
          }
      }
  }
)

  1. $avg:求平均值
db.acct.aggregate(
  {
      $group: {
          '_id':'acct_type',
          avg_value:{
              $avg:'balance',
          }
      }
  }
) 
    
  1. $project:集合中查询指定的域
    类似于sql的投影运算
    e.g. 现在从acct集合中查询账户和户名。
  db.acct.aggregate(
      {
          _id:0,
          '账号':'$acct_no',
          '户名':'$acct_name'
      }
  )
  

类似于 select acct_no as "账号", acct_name as "户名" from acct
在mongo里面称为投影聚合

5) $match: 对账号数据进行过滤
e.g. 查询账户余额小于5000的账号

db.acct.aggregate(
  {
      $match:{
          balance:{
              $lt:5000
          }
      }
  }
)

6)$sort :排序
查询所有账号数据

db.acct.aggregate(
  {
      $sort: {
          balance:-1
      }
  }
)

-1 表示降序, 1表示升序

7)管道聚合:上一个操作完成后,将结果作为下一个操作的输入
e.g. 对acct集合根据acct_type进行筛选,然后对筛选结果按照账户进行降序排序

db.acct.aggrgate(
   {
      $match:{
          acct_type:1
      },
   },
   {
      $sort:{
          acct_no:-1
      }
   }    
)

  1. 固定集合 (Capped Collections)
  1) 什么是固定集合
  - 有固定大小的集合(存储空间,笔数)
  - 当数据大小/笔数超过上限后
  再插入新的数据会覆盖初始头部的数据
  
  - 优点:
    插入速度快,顺序查找快
    能够淘汰早期数据
    控制集合大小
    应用场景
    日志
    临时缓存
            

如何创建固定集合:

-语法:

db.createCollection(
  {
     集合名称,
     {
         capped:true,
         size:10000,
         max:100
     }
  }
)

capped: 设置为true,表示创建固定集合
size:集合的大小,单位bytes max:最多存放多少个文档
e.g. 创建集合log,限定最多存储3笔数据

db.createCollection(
  {
      'log',
      {
          capped:true,
          size:10000,
          max:3,
      }
  }
)

插入数据,第4笔就会覆盖前面的数据

db.log.insert(
  {
      name:"Jerry",
      oper:'delete',
  }
)

db.log.insert(
  {
      name:"Tom",
      oper:'delete',
  }
)

db.log.insert(
  {
      name:"Tom",
      oper:'delete',
  }
)

课堂练习

1)统计订单笔数
db.orders.find().count()

2)查询所有订单,按照下单时间倒叙显示

db.orders.find().sort({order_date:-1}).pretty()

3)修改某个订单的状态

db.orders.update(
  {
      {order_id:"201801010101"},
      {set:{
              status:2,
           }
      },
      false,
      false,
  }
)

4)为所有订单添加一个状态,支付状态 payment_status
5)查询所有订单中,包含了编号为"P0001"商品的订单
6)在订单集合的订单编号(order_id)域创建升序所有
7)为某个订单添加备注信息(要求为字符串数组)
8)删除一笔无效订单,(订单状态删除,值自定)

db.orders.insert(
  {
      order_id:"2411673791",
      cust_name:"baiyanfeng",
      order_date:new Date(),
      payment_status:0,
      order_detail:[
          {
              product_id:"P0026",
              product_name:"js",
              amt:1,
              price:202151,
          }
      ]
  }
)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容