MongoDB笔记

一、业务应用场景

三高需求:

  • 高并发读写需求
  • 海量数据的高效率存储和访问的需求
  • 对数据库的高扩展性和高可用性的需求

应用场景:

  • 社交场景,使用MongoDB存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人,地点等功能
  • 游戏场景:方便查询、高效率存储和访问
  • 物流场景:使用MongoDB存储订单信息
  • 物联网场景:存入智能设备信息
  • 视频直播:存储用户点赞、互动信息等

共同的特点:

  • 数据量大
  • 写入操作频繁(读写都很频繁)
  • 价值低的数据,对事务的要求不高

什么时候选择mongoDB:

  • 不需要事务及复杂的join支持
  • 数据模型无法确定,想快速迭代开发
  • 需要2000-3000以上的QPS
  • 需要能够快速水平扩展
  • 要求存储的数据不丢失
  • 99.9999%可用
  • 大量地理位置查询、文本查询

二、MongoDB简介

最像关系型数据库(MySQL)的非关系型数据库
特点:
高性能、高可用性、高扩展性、丰富的查询支持

三、单机部署

MongoDB的安装:

参考这篇文章:https://blog.csdn.net/weixin_70319460/article/details/126436904

基本命令

选择和创建数据库的语法格式:

选择和创建数据库的格式:
use 数据库名称
如果数据库不存在则自动创建,以下语句创建spitdb数据库
use articledb
查看有权限查看的所有的数据库命令
show dbsshow databases

注意:在MongoDB中,集合在内容插入后才会创建,就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正的创建

查看当前正在使用的数据库命令
db
MongoDB中默认的数据库为test,如果没有选择数据库,集合将存放在test数据库中
另外:
数据库名可以满足以下条件的任意UTF-8字符串

  • 不能是空字符串
  • 不得含有'' (空格) . $ / \和\0 (空字符)
  • 应全部小写
  • 最多64个字节

有些数据库名是保留的,可以直接访问这些有特殊作用的数据库

  • admin:从权限的角度看,这是root数据库,要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限,一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器
  • local:这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
  • config:当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息

数据库的删除:

dp.dropDatabase()
提示:用来删除已经持久化的数据库

集合操作

集合就相当于关系数据库中的表

显示创建:

可以显示创建,也可以隐式的创建
基本语法格式:
db.createCollection(name)
参数说明:

  • name:要创建的集合名称

例如:创建一个名为myCollection的普通集合
db.createCollection("mycollection")
查看当前库中的表:show tables或者show collections命令

隐式创建:

向一个集合中插入另一个文档的时候,如果集合不存在,则会自动创建集合
详见 文档的插入章节
提示:通常我们使用隐式创建文档即可

集合的删除:

db.collection名称.drop()

文档的CRUD

文档(document)的数据结构和JSON基本一样
所有存储在集合中的数据都是BSON格式

文档的插入:

1.单个文档插入

使用insert()或save()方法向集合中插入文档,语法如下:

db.collection名称.insert(   
	<document or array of document>,
	{
  	writeConcern:<document>,
  	ordered:<boolean>
  }
)

参数:
document、writeConcern、ordered
insert可以直接插入json

2.批量插入
db.collection名称.insertMany(
	[<document 1>,<document 2>,...],
	{
  	writeConcern:<document>,
  	ordered:<boolean>
  }	
)

文档的基本查询:

1.查询所有

如果我们查询split集合的所有文档,我们输入以下命令
db.comment.find()或者db.comment.find({})
这里你会发现每条文档有一个叫_id的字段,这个相当于原来关系型数据库中的主键,没有指定该字段时,MongoDB会自动创建,其类型是ObejectID类型
如果我们在插入文档记录时指定该字段也可以,其类型可以是ObjectID类型,也可以是MongoDB支持的任意类型
如果想查询userid为1003的记录
db.comment.find({userid:'1003'})
可能会返回满足条件的很多条,如果只想获取第一条则
db.comment.findOne({userid:'1003'})

2.投影查询

如果查询结果返回部分字段,则需要使用投影查询(不显示所有字段,只显示指定字段)

db.comment.find({userid:"1003"},{userid:1,nickname:1,_id:0})

在批量插入由于数据较多容易失败,因此可以使用try-catch进行异常处理,测试的时候可以不处理(了解)

文档的更新:

db.collection.update(query, update, options)

1.覆盖的修改

如果修改_id为1的记录,点赞量为1001,输入以下语句:
db.comment.update({_id:"1"},{likenum:NumberInt(1001)})
执行后会发现这条记录的除了likenum字段,其他字段都不见了

2.局部修改

为了解决这个问题,我们需要使用修改器\(set来实现,命令如下: 我们想修改_id为2的记录,浏览量为889,输入以下语句: `db.comment.update({_id,"2"},{\)set:{likenum:NumberInt(889)}})`
这样就OK了

3.批量的修改

更新所有用户为1003的用户昵称为喵喵队,默认是只修改第一条

db.comment.update({userid:"1003"},{$set:{nickname:"喵喵队"}},{multi:true})
4.列值增长的修改

如果我们想实现对某列值在原有值基础上进行增加或减少,可以使用$inc运算符来实现
需求:对3号数据的点赞数,每次递增1
db.comment.update({_id:"3"},{$inc:{likenum:NumberInt(1)}})

文档的删除

删除文档的语法结构:
db.集合名词.remove(条件)
以下语句可以将数据全部删除,请慎用
db.comment.remove({})
如果删除_id=1的记录,输入以下语句
db.comment.remove({_id:"1"})

文档的分页查询

1.统计查询

统计查询使用count()方法,语法如下
db.collection.count(query, options)
参数:query是查询选择条件、options可选,是用于修改计数的额外选项
实例:

  • 统计所有记录数

统计comment集合的所有的记录数:
db.comment.count()

  • 按条件统计记录数

统计userid为1003的记录条数
db.comment.count({userid:"1003"})
提示:
默认情况下count()方法返回符合条件的全部纪录条数

2.分页列表查询

可以使用limit()方法来读取指定数量的数据,使用skip()方法来跳过指定数量的数据
基本语法如下所示:
db.collection_name.find().limit(NUMBER).skip(NUMBER)
如果想要返回指定条数的记录,可以在find方法后调用limit来返回结果(TopN),默认值20,例如:
db.comment.find().limit(3)
skip方法同样接收一个数字参数作为跳过的记录条数(前N个不要),默认值是0
db.comment.find().skip(3)
分页查询:

# 第一页
db.comment.find().skip(0).limit(2)
# 第二页
db.comment.find().skip(2).limit(2)
# 第三页
db.comment.find().skip(4).limit(2)

3.排序查询

sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用1和-1来指定排序的方式,其中1为升序排列,而-1是用于降序排列
语法如下所示:
db.collection_name.find().sort({key:1})
或者
db.集合名称.find().sort(排序方式)
例如:
对userid降序排列,并对访问量进行升序排列
db.comment.find().sort({userid:-1,likenum:1})

文档更多的查询

1.正则的复杂条件查询

MongoDB的模糊查询是正则表达式方式实现的,格式为
db.collection.find({field:/正则表达式/})

db.集合.find({字段:/正则表达式/})
提示:正则表达式是js语法,直接量的写法

2.比较查询

<,<=,>,>= 这个操作符也是很常用的,格式如下:

db.集合名称.find({"field":{ $gt: value }}) // 大于: field> value
db.集合名称.find({"field":{ $lt: value }}) // 小于: field< value
db.集合名称.find({"field":{ $gte: value }}) // 大于等于: field >= value
db.集合名称.find({"field":{ $lte: value }}) // 小于等于: field <= value
db.集合名称.find({"field":{ $ne: value }})  // 不等于: field != value

实例:查询评论点赞数量大于700的记录
db.comment.find({likenum:{$gt:NumberInt(700)}})

3.包含查询

包含使用\(in操作符 示例:查询评论的集合中userid字段包含1003或1004的文档 `db.comment.find({userid:{\)in:["1003","1004"]}})不包含使用$nin操作符 示例:查询评论的集合中userid字段不包含1003或1004的文档db.comment.find({userid:{$nin:["1003","1004"]}})`

4.条件连接查询

如果我们需要查询两个以上条件,需要使用\(and操作符进行关联(相当于SQL的and) `\)and:[{},{},{}]示例:查询评论集合中likenum大于等于700 且小于2000的文档db.comment.find(\(and:[{likenum:{¥gte:NumberInt(700)}},{likenum:{\)lt:NumberInt(2000)}}])如果两个以上条件是或者的关系,我们使用操作符进行关联,与前面and的使用方式相同$or:[{},{},{}]`

索引-Index

mySQL的索引使用的是B+树,MongoDB的索引使用的是B树

索引为的类型

1.单字段索引

MongoDB支持在单个字段上创建用户定义的升序/降序索引,称为单字段索引,对于单个字段索引和排序操作,索引键的排序顺序(升序或降序)并不重要,因为MongoDB可以在任何方向上遍历索引

2.复合索引

复合索引中列出的字段顺序具有重要意义,比如复合索引由{userid:1,score:-1}组成,则索引首先按userid正序排序,然后在每个userid的值内,再按照score倒序排序

3.其他索引

地理空间索引、文本索引、哈希索引

索引的管理操作

在集合上创建索引

db.collection.createIndex(keys, options)
建立单个索引
db.comment.createIndex({userid:1})
建立复合索引
db.comment.createIndex({userid:1,nickname:-1})

索引的移除

指定索引的移除
db.collection.dropIndex(index)
所有索引的移除
db.collection.dropIndexes()

索引的使用

执行计划

分析查询性能,通常使用执行计划查看查询的情况比如查询耗费时间,是否基于索引查询等
通常我们想知道,建立的索引是否有效,效果如何都需要通过执行计划查看
db.collection.find(query,options).explain(options)

涵盖的查询

当查询条件和查询的投影仅包含索引字段时,MongoDB直接从索引返回结果,而不扫描任何文档或将文档带入内存,这些覆盖的查询可以非常有效

副本集的创建

添加副本从节点

rs.add(host, arbiterOnly)

副本集的数据读写操作

设置奴隶节点,允许从成员上运行读的操作
语法:
rs.slaveOk()或者rs.slaveOk(true)想取消的话把true改成false
仲裁者节点,不存放任何业务数据,可以登录查看

主节点的选举原则

MongoDB在副本集中,会自动进行主节点的选举,主节点选举的触发条件

  • 主节点故障
  • 主节点网路不可达(默认心跳信息是10s)
  • 人工干预(rs.stepDown(600))

一旦触发选举,就要根据一定的规则来选取主节点
选举规则是根据票数来决定谁获胜

  • 票数最高,且获得了"大多数"成员的投票支持的节点获胜

“大多数”的定义为,假设复制集内投票成员数量为N,则大多数为N/2+1,例如:3个投票成员,则大多数的值是2,当复制集内存活成员数量不足大多数时,整个复制集将无法选举出Primary,复制集将无法提供写服务,处于只读状态

  • 若票数相同,且都获得了大多数成员的投票支持,根据新的节点获胜

数据的新旧是通过操作日志oplog来对比的

分片集群

分片是一种跨多台机器分布数据的方法,MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署
分片集群包含:

  • 分片(存储):每个分片包含分片数据的子集,每个分片都可以部署为副本集
  • mongos(路由):mongos充当查询路由器,在客户端应用程序和分片集群之间提供接口
  • config servers ("调度"的配置):配置服务器存储群集的元数据和配置设置,从MongoDB3.4开始,必须将配置服务器部署为副本集(CSRS)
posted @ 2023-05-23 18:39  喵喵队立大功  阅读(40)  评论(0编辑  收藏  举报