mongoDB基本, 2022-08-26

(2022.08.26 Thur)

本文包括

  • mongoDB的应用场景
  • 数据架构
  • 高可用与高扩展
  • 基础语法、索引
  • 存储引擎
  • ObjectID对象

MongoDB是一个基于分布式文件存储的数据库。用C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

mongoDB的缺点是占用空间比SQL大。

mongoDB的应用场景

以MongoDB为代表的文档数据库最大特点是no-schema,可以存储和读取任意的数据,目前绝大多数文档数据库存储的数据格式是JSON/BSON,因为JSON是自描述的,无需在使用前定义字段。

no-schema的特点带来了一些优势:

  • 新增字段简单
  • 历史数据不会出错
  • 可以容易存储复杂数据

文档数据库的缺点之一是不支持事务,对事务要求严格的场景不适合使用文档数据库。另一个缺点是无法使用SQL中的join操作。更适合作为SQL数据库的补充。

数据架构

mongodb data architecture

磁盘文件经过加载之后形成 MongoDB实例,实例中可以存放多个数据库(图示仅展示一个数据库)。每个数据库中存放的是Collection,集合中存放Document,Document 中存放 Field。

这里提到的集合、文档、字段等与SQL对应关系如下

SQL术语 mongoDB术语
database database
table collection
row document
volume/field field

高可用与高扩展

MongoDB 的数据复制架构是保障 MongoDB 实现数据保护的重要基础条件。


data replication

复制集(Replica Set)是mongoDB的数据复制架构。通常是三个对等的节点构成一个复制集,有Primary和Secondary两种角色,其中 Primary负责读写请求,Secondary负责读请求,可以通过配置实现。Primary和Secondary节点之间在数据写入过程当中实现数据的异步复制。节点之间通过Heartbeat实现健康侦测,当Primary失败,集群可以通过多数派选举新的Primary,并且实现Failover机制。

我们再来看现实场景当中使用比较多的相对比较复杂的分切分布式集群架构,也就是高扩展架构

high scalable

从图示架构可以看出,分片集群的优势在于提供类似线性增长的架构,提高数据可用性,提高大型数据库查询服务器的性能。当 MongoDB 单点数据库服务器存储成为瓶颈、单点数据库服务器的性能成为瓶颈或需要部署大型应用以充分利用内存时,可以使用分片技术。

整体架构有几个重要的组件:切片(Shard)、配置服务器(ConfigServer、路由(Query Router)。那么他们的逻辑关系又是什么样的呢?各自承担了什么的角色呢?

  • Shard :用于存储实际的数据块,一个切片服务器角色可由几台机器组成,防止主机单点故障。
  • Config Server :MongoDB 实例,存储了整个 ClusterMetadata ,其中包括 chunk 信息。
  • Query Routers :客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。

基于以上组件功能角色,我们来分析客户端的访问路径为:首先、客户端访问路由( Query Router )的统一接口层,由路由层将数据请求发送到特定的配置服务器( ConfigServers );接着,由配置服务器查询本地的元数据信息定位到要访问的数据在哪个切片服务器( Shard )上;最后,客户端直接访问到切片服务器的具体位置,获取自己所需的数据信息。

MongoDB 的数据划分,是以集合级别为标准。分片通过 Shard Key 来划分集合数据。具体切片的策略可以是通过数据的范围划分来切分,也可以通过哈希策略来切分,具体需要考虑到数据的特点和集群数据访问的效率。

基础语法、索引

(2022.08.29 Mon)
在docker的bash环境中进入mongodb

>> docker exec -it  /bin/bash
>> mongo

基本查看

查看数据库、collections

> show databses;
> show dbs;
> use ; # 进入某数据库
> show collections;
> show tables; # 与show collections等效

新增

创数据库和collections

> db.createCollection(''); # 创建collection

新增collection中的文本

> data = {'name': 'abc', 'age': 100, 'genre': 'pop'}
> db..insert(data);
WriteResult({ "nInserted" : 1 })

执行insert操作之后,mongdoDB系统会自动为这条记录添加一个id,_id。因此,即便添加的两条记录的字段和内容完全一致,也会因为_id的不同而作为不同的文本存在。

查询

  • 展示collection中的所有信息
> db..find();
> db..find().pretty(); # 展示格式经过美化
  • 根据特定条件查询信息
> cond = {'b': 103};
> db..find(cond); 
> db.testdb.find(cond);
{ "_id" : ObjectId("630c6f6499e641685ec2b80b"), "b" : 103 }
{ "_id" : ObjectId("630c76f099e641685ec2b80d"), "b" : 103, "test" : 999, "age" : 18 }

根据条件指定的范围查询信息,需要采用诸如

{key: {$xx: value}};

的格式来指定查询条件的变量和范围。其中的xx代表了范围,大于gt,小于lt,大于等于gte,小于等于lte,不等于ne,等于eq,反not。比如查询b大于101的所有记录。

> cond = {'b': {$gt: 101}};
> db..find(cond);
{ "_id" : ObjectId("630c5f4299e641685ec2b808"), "b" : 102 }
{ "_id" : ObjectId("630c61e1529d851b783347f2"), "b" : 103, "text" : 1 }
{ "_id" : ObjectId("630c76f099e641685ec2b80d"), "b" : 103, "test" : 999, "age" : 18 }

查询b不等于102的所有记录。

> cond = {'b': {$ne: 102}};
> cond1 = {'b': {$not: {$eq: 102}}}; # cond和cond1等价
> db.<>.find(cond); 
{ "_id" : ObjectId("630c5dd599e641685ec2b806"), "datatime" : "2022-04-12", "location" : "Harbin", "event" : "terminate contract", "db" : "mongodb" }
{ "_id" : ObjectId("630c5f3099e641685ec2b807"), "b" : 101 }
{ "_id" : ObjectId("630c61e1529d851b783347f2"), "b" : 103, "text" : 1 }
{ "_id" : ObjectId("630c76f099e641685ec2b80d"), "b" : 103, "test" : 999, "age" : 18 }

根据多个条件查询。条件之间可以有多种关系,1) and,2) or。不同的条件分别用字典存储,写成{key: value}的格式,并保存在一个列表中[ ]

db..find({$xx: [{key1: value1},{key2: {$xx: value}}]});

多个条件同时满足,使用and关键字

> db.testdb.find({$and: [{'b': {$gt:100}},{'test':111}]});
{ "_id" : ObjectId("630c6fbc99e641685ec2b80c"), "b" : 103, "test" : 111 }

多个条件可单独满足,使用or关键字

> db.testdb.find({$or: [{'b': {$gt:101}},{'test':111}]});
{ "_id" : ObjectId("630c5f4299e641685ec2b808"), "b" : 102 }
{ "_id" : ObjectId("630c61e1529d851b783347f2"), "b" : 103, "text" : 1 }
{ "_id" : ObjectId("630c76f099e641685ec2b80d"), "b" : 103, "test" : 999, "age" : 18 }

删除

删除数据库和collection

> db.dropDatabase(); # 删除db
> db..drop(); # 删除collection

删除文档,使用命令如

cond = {key: value};
db..remove(cond, {justOne: , writeConcern: });

删除文档时,通过cond给出删除文档满足的条件,比如这个案例中删除b=100的文档。justOne是可选参数,boolean类型,表示是否仅删除满足条件的一个文档还是所有文档,默认删除所有文档,如果只删除一个,则标记为1true

> cond = {'b': 100};
> db..remove(cond,1); # 仅删除一个满足条件的数据,不加`1`则删除所有满足条件的数据
WriteResult({ "nRemoved" : 1}

(2022.08.30 Tues)

更新

mongodb的数据更新使用update命令。更新的格式为

db..update(, , {upsert: ,
multi: , writeConcern: })

格式中的代表查询条件,如对b=103的所有记录做修改,则{b: 103}

代表更新操作,共分为六种

  • $set:设定某字段为新值
  • $inc:设定字段值的自增/减量
  • $unset:删除指定的字段
  • $push:在数组的结尾加入一个元素/数组,格式为$push: {: [xxx]},push数组则添加数组,push元素则添加元素
  • $pull:从数组中删除元素,如果有多个满足条件的,则全部删除
  • $pop:从数组的结尾或开头删除一个元素,通过设置标志位指定是从结尾删还是开头删,1结尾0开头,格式为$pop: {: 1}

后面是可选参数,共三个

  • $upsert:如果不存在update的记录,是否插入新对象,true为插入,默认是false,不插入,即update+insert
  • $multi:是否更新多条满足条件的记录,默认false即只更新一条满足条件的记录,参数为true则更新全部满足条件的记录。
  • $writeConcern:抛出异常级别

更新的命令案例

> db..update({b: 3}, {$set:{'age': 26}}, {multi: true})
> db..update({b: 105, test: 100}, {$inc: {age: 10}}, true, true); # 结尾的两个true,分别表示为如果没有该对象则插入,和所有符合条件的记录都执行该操作;该案例中没有`b:105`这个对象,所以执行insert
WriteResult({
    "nMatched" : 0,
    "nUpserted" : 1,
    "nModified" : 0,
    "_id" : ObjectId("630d90f0529d851b78334af0")
})

ObjectID对象

(2022.09.23 Fri)
在mongoDB中使用ObjectId()命令可以生成一个12字节(byte)的ObjectId对象。上面的案例中,每个记录都对应了一个独一无二的_id,比如ObjectId("630d90f0529d851b78334af0")(共24位16进制数),其中包括

  • 4字节时间戳(timestamp),是ObjectId的创建时间,以Unix epoch的秒数度量,即前4位
  • 5字节的随机值,该值对机器和进程来说独一无二
  • 3字节增量计数器(incrementing counter),初始值随机,即后6位

ObjectId的内置方法包括下面几种

  • ObjectId().getTimestamp():返回ObjectId中时间的部分,以ISO形式,如
> ObjectId("632c0e025cc2e01646951254").getTimestamp()
ISODate("2022-09-22T07:25:54Z")
  • ObjectId().toString():返回JavaScript表达,以string形式ObjectId(...)
> ObjectId("632c0e025cc2e01646951254").toString()
ObjectId("632c0e025cc2e01646951254")
  • ObjectID.valueOf():返回ObjectId的16进制字符表达(hexadecimal),返回字符
> ObjectId("632c0e025cc2e01646951254").valueOf()
632c0e025cc2e01646951254

Reference

1 mongodb 官方文档
2 mongodb 百度百科
3 NoSQL DB 系列解读:一文看懂 MongoDB,微信公众号TWT企业IT社区

你可能感兴趣的:(mongoDB基本, 2022-08-26)