走进 MongoDB

一、MongoDB 的相关概念

MongoDB 的功能定位

走进 MongoDB

定位上 ,MongoDB 介于 Memcached 和关系型数据库之间,扩展性和性能上, MongoDB 更接近于 Memcached,功能上,MongoDB 更接近于关系型数据库。

(一)MongoDB 部署模型

走进 MongoDB

在生产环境中,MongoDB 经常会部署成一个三节点的复制集,或者一个分片集群。

我们先来看左边。当 MongoDB 部署为一个复制集时,应用程序通过驱动,直接请求 复制集中的主节点,完成读写操作。


另外两个从节点,会自动和主节点同步,保持数据的更新。


在集群运行的过程中,万一主节点遇到故障,两个从节点会在几秒的时间内选举出新的 主节点,继续支持应用的读写操作。


我们再来看右边,当 MongoDB 被部署为一个分片集群时,应用程序通过驱动,访问 路由节点,也就是 Mongos 节点 Mongos 节点会根据读写操作中的片键值,把读写操作分 发的特定的分片执行,然后把分片的执行结果合并,返回给应用程序。


那集群中的数据是如何分布的呢?这些元数据记录在 Config Server 中,这也是一个 高可用的复制集。每个分片管理集群中整体数据的一部分,也是一个高可用复制集。此外, 路由节点,也就是 Mongos 节点在生产环境通常部署多个。这样,整个分片集群没有任何 单点故障。


(二)MongoDB 基本概念与关系数据的对应关系

走进 MongoDB

关系型数据通常有数据库和表的概念,对应在 MongoDB 里有数据库和集合关系;数据 库有主表和子表,对应 MongoDB 通常使用内嵌的子文档或内嵌数组;关系型数据里有 Index 索引,MongoDB 也有类似概念;关系数据库里一条数据称为一行,MongoDB 称为 一个文档 Document;关系型数据库里面的列,对应到 MongoDB 成为一个字段 Field;关 系数据库里面经常使用 Join 连接操作,对应 MongoDB 通常使用内嵌方式解决,如果使用 Linking 方式,对应使用$Lookup 操作符也可支持左外链接;关系型数据库里面还有视图, 对应 MongoDB 也有只读视图和按需物化视图;关系型数据库里面会有 ACID 的多记录事 务,对应的 MongoDB 里面会有 ACID 的多文档事务。


(三)MongoDB 的数据层次结构

MongoDB 里面数据主要分为三层,文档(Documents),集合(Collections), 和 数据库(Databases),多个文档是存储在一个集合中,多个集合存放在一个数据库里,每 个集群里面可能会有多个数据库。


例如:


  • 数据库(Database): Products
  • 集合(Collections): Books, Movies, Music

数据库和集合的组合,构成 MongoDB 的命名空间:

  • Products.Books
  • Products.Movies
  • Products.Music


*数据库名最长不能超过 64 个字节,命名空间最长不能超过 120 字节 *FCV>=4.4,命名空间长度限制为 255 字节

(四)MongoDB 的数据结构

MongoDB 采用 JSON 文档结构:

  • JSON 的全称:JavaScript Object Notation
  • JSON 的格式:支持如下数据格式
     字符串 :e.g., “Thomas”
     数字 :e.g., 29, 3.7)
     布尔:True / false
     空值:Null
     数组:e.g., [88.5, 91.3, 67.1]
     对象:Object
{
"firstName": "Thomas",
 "lastName": "Smith",
 "age": 29
}


(五)MongoDB 采用 BSON 格式保存数据

MongoDB 数据类型

走进 MongoDB

走进 MongoDB

上图是 MongoDB 数据类型的一些列表,常见类型 MongoDB 几乎都支持。


二、集群部署

安装你的第一个 MongoDB 系统

第一个命令:下载

curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4. 4.2.tgz

第二个命令:解压

tar xzvf mongodb-linux-x86_64-rhel70-4.4.2.tgz

第三个命令:改个目录名

mv mongodb-linux-x86_64-rhel70-4.4.2 mongodb

第四个命令:没了!


运行 MongoDB

/bin/mongod --dbpath /data/db

[代码注释]

[/bin/mongod]:MongoDB 安装的 bin 目录

[data/db]:MongoDB 数据文件的位置


访问 MongoDB

$ ./bin/mongo MongoDB

//安装的 bin 目录

MongoDB shell version: 4.4.2 
... 
Server has startup warnings: 
2020-12-15T04:23:25.268+0000 I CONTROL[initandlisten] 
2020-12-15T04:23:25.268+0000 I CONTROL [initandlisten] ** WARNIN
G: Access control is not enabled for the database.
 ...

创建复制集练习

1. 创建数据目录:

mkdir rs1 rs2 rs3

2. 启动三个 MongoDB 服务

mongod --replSet rs --dbpath ./rs1 --port 27017 --fork --logpath ./rs 1/mongod.log 
mongod --replSet rs --dbpath ./rs2 --port 27018 --fork --logpath ./rs 2/mongod.log 
mongod --replSet rs --dbpath ./rs3 --port 27019 --fork --logpath ./rs 3/mongod.log

3. 连接 MongoDB 服务:

mongo //connect to the default port 27017

4. 指定复制集配置

rs.initiate() // 初始复制集 
rs.add ('<HOSTNAME>:27018') // 增加一个节点配置 
rs.add('<HOSTNAME>:27019') // 增加一个节点配置 
rs.status()


创建分片集群练习

有以下 5 个步骤:

1. 创建 Config Server 复制集

2. 创建一个或多个分片(每个分片为一个复制集)

3. 启动 Mongos(一个或多个)

4. 访问 Mongos,把分片添加到集群

5. 选择片键,启用分片


以上就完成整个分片集群的部署。


生产环境部署建议


生产环境当中,大家应该遵循生产环境部署的一些最佳实践。比如:


1. 容量规划:计算资源,存储容量,IOPS,Oplog,网络带宽

2. 高可用:部署复制集或分片集群

3. 节点个数:复制集部署奇数个节点,避免脑裂

4. 应用生产环境的最佳实践,如:


  • 使用主机名而不是 IP
  • 文件系统(Linux 环境推荐 XFS)
  • 禁用 NUMA
  • 禁用 THP
  • 调高资源限制
  • Swappiness
  • Readahead
  • Tcp_Keepalive_Time
  • 时钟同步
  • 安全配置

三、基本操作

插入新文档

insertOne db.products.insertOne( { item: "card", qty: 15 } );
insertMany 
db.products.insertMany( [ { _id: 10, item: "large box", qty: 20 }, { _id: 11, item: "small box", qty: 55 }, { _id: 12, item: "medium box", qty: 30 } ] ); 
Insert db.collection.insert( <document or array of documents>, { writeConcern: <document>, ordered: <boolean> } )

删除文档

deleteOne 
db.orders.deleteOne( { "_id" : ObjectId("563237a41a4d68582c2509da") } ); 
db.orders.deleteOne( { "expirationTime" : { $lt: ISODate("2015-11-01T12:40:15Z") } } ); 
deleteMany 
db.orders.deleteMany( { "client" : "Crude Traders Inc." } ); 
remove 
db.collection.remove( <query>, <justOne> )

删除集合和数据库

使用 Drop 删除集合


  • 使用 DB..Drop()来删除一个集合
  • 集合中的全部文档都会被删除.
  • 集合相关的索引也会被删除


db.colToBeDropped.drop()

使用 DropDatabase 删除数据库

  • 使用 DB.dropDatabase()来删除数据库
  • 数据库相应文件也会被删除,磁盘空间将被释放


use tempDB 
db.dropDatabase() 
show collections // No collections 
show dbs // The db is gone

使用 Find 查询数据文档


Find 是 MongoDB 的基础查询命令

Find 返回数据的游标(Cursor)

db.movies.find( { "year" : 1975 } ) //单条件查询 
db.movies.find( { "year" : 1989, "title" : "Batman" } ) //多条件 and 查询 
db.movies.find( { $or: [{"year" : 1989}, {"title" : "Batman"}] } ) //多条件 or 查询 
db.movies.find( { $and : [ {"title" : "Batman"}, { "category" : "action" }] } ) // and 查询 
db.movies.find( { "title" : /^B/} ) //按正则表达式查找

SQL 查询条件对照

a = 1 -> {a: 1} 
a <> 1 -> {a: {$ne: 1}} 
a > 1 -> {a: {$gt: 1}} 
a >= 1 -> {a: {$gte: 1}} 
a < 1 -> {a: {$lt: 1}} 
a <= 1 -> {a: {$lte: 1}} 
a = 1 AND b = 1 -> {a: 1, b: 1}或{$and: [{a: 1}, {b: 1}]} 
a = 1 OR b = 1 -> {$or: [{a: 1}, {b: 1}]} 
a IS NULL -> {a: {$exists: false}} 
a IN (1, 2, 3) -> {a: {$in: [1, 2, 3]}}

查询操作符

$lt: 存在并小于 
$lte: 存在并小于等于 
$gt: 存在并大于 
$gte: 存在并大于等于 
$ne: 不存在或存在但不等于 
$in: 存在并在指定数组中 
$nin: 不存在或不在指定数组中 
$or: 匹配两个或多个条件中的一个 
$and: 匹配全部条件

更新操作

Update 操作需要执行参数

参数包括

  • 查询参数
  • 更新参数
// insert data 
db.movies.insert( [ 
    { 
  "title" : "Batman", 
  "category" : [ "action", "adventure" ],
  "imdb_rating" : 7.6,
  "budget" : 35 
  }, 
  { 
  "title" : "Godzilla", 
  "category" : [ "action", "adventure", "sci-fi" ], 
  "imdb_rating" : 6.6 }, 
  { 
  "title" : "Home Alone", 
  "category" : [ "family", "comedy" ], 
  "imdb_rating" : 7.4 } 
  ] ) 
  db.movies.update( { "title" : "Batman" }, { $set : { "imdb_rating" : 7.7 } } )
//"title" : "Batman" :查询蝙蝠侠
//$set : { "imdb_rating" : 7.7 }:更新 IMDB 评分字段

Update 更新数组操作

$Push: 增加一个对象到数组底部

$PushAll: 增加多个对象到数组底部.

$Pop: 从数组底部删除一个对象

$Pull: 如果匹配指定的值或条件,从数组中删除相应的对象.

$PullAll: 如果匹配列表中的任意值,从数组中删除相应的对象

$AddToSet: 如果不存在则增加一个值到数组


使用 {Upsert: True} 更新或插入

如果希望没有就添加,指定 Upsert: True 参数

默认情况下如果没有匹配的对象,就不会执行更新

db.movies.update( { "title" : "Jaws" }, { $inc: { "budget" : 5 } }, 
{ upsert: true } )
// upsert: true  :如果找不到“大白鲨”
//就增加一个“大白鲨”电影
{ 
“_id” : ObjectId("5847f65f83432667e51e5ea8"), 
"title" : "Jaws", 
"budget" : 5 
}

快速掌握MongoDB核心技术目录

电子书下载《玩转MongoDB从入门到实战》 https://developer.aliyun.com/article/780915
走进 MongoDB  https://developer.aliyun.com/article/781079
MongoDB聚合框架 https://developer.aliyun.com/article/781095
复制集使用及原理介绍  https://developer.aliyun.com/article/781137
分片集群使用及原理介绍  https://developer.aliyun.com/article/781104
ChangeStreams 使用及原理 https://developer.aliyun.com/article/781107
事务功能使用及原理介绍 https://developer.aliyun.com/article/781111
MongoDB最佳实践一 https://developer.aliyun.com/article/781139
MongoDB最佳实践二  https://developer.aliyun.com/article/781141
上一篇:【分享】小程序购物车demo演示实例(全选与不全选、数量加减、价格汇总、删除提示)


下一篇:MongoDB 最佳实践二