原文地址:https://blog.csdn.net/devcloud/article/details/102629922 遵循 CC 4.0 BY-SA 版权协议

MongoDB 数据库的一些特性:

  • 面向文档存储,基于JSON/BSON 可表示灵活的数据结构
  • 动态 DDL能力,没有强Schema约束,支持快速迭代
  • 高性能计算,提供基于内存的快速数据查询
  • 容易扩展,利用数据分片可以支持海量数据存储
  • 丰富的功能集,支持二级索引、强大的聚合管道功能,为开发者量身定做的功能,如数据自动老化、固定集合等等。
  • 跨平台版本、支持多语言SDK..

MongoDB概念

  • database 数据库,与SQL的数据库(database)概念相同,一个数据库包含多个集合(表)

  • collection 集合,相当于SQL中的表(table),一个集合可以存放多个文档(行)。 不同之处就在于集合的结构(schema)是动态的,不需要预先声明一个严格的表结构。更重要的是,默认情况下 MongoDB 并不会对写入的数据做任何schema的校验。

  • document 文档,相当于SQL中的行(row),一个文档由多个字段(列)组成,并采用bson(json)格式表示。

  • field 字段,相当于SQL中的列(column),相比普通column的差别在于field的类型可以更加灵活,比如支持嵌套的文档、数组。

    此外,MongoDB中字段的类型是固定的、区分大小写、并且文档中的字段也是有序的。

SQL约束及其他操作概念:

  • _id 主键,MongoDB 默认使用一个_id 字段来保证文档的唯一性。
  • reference 引用,勉强可以对应于 外键(foreign key) 的概念,之所以是勉强是因为 reference 并没有实现任何外键的约束,而只是由客户端(driver)自动进行关联查询、转换的一个特殊类型。
  • view 视图,MongoDB 3.4 开始支持视图,和 SQL 的视图没有什么差异,视图是基于表/集合之上进行动态查询的一层对象,可以是虚拟的,也可以是物理的(物化视图)。
  • index 索引,与SQL 的索引相同。
  • $lookup,这是一个聚合操作符,可以用于实现类似 SQL-join 连接的功能
  • transaction 事务,从 MongoDB 4.0 版本开始,提供了对于事务的支持
  • aggregation 聚合,MongoDB 提供了强大的聚合计算框架,group by 是其中的一类聚合操作。

SQL to MongoDB Mapping Chart

操作语法

MongoDB CRUD Operations

除了文档模型本身,对于数据的操作命令也是基于JSON/BSON 格式的语法。

插入操作:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
db.book.insert(
{
  title: "My first blog post",
  published: new Date(),
  tags: [ "NoSQL", "MongoDB" ],
  type: "Work",
  author : "James",
  viewCount: 25,
  commentCount: 2
}
)

查找:

1
db.book.find({author : "James"})

更新

1
2
3
4
db.book.update(
   {"_id" : ObjectId("5c61301c15338f68639e6802")},
   {"$inc": {"viewCount": 3} }
)

删除:

1
db.book.remove({"_id": ObjectId("5c612b2f15338f68639e67d5")})

查询返回指定的字段

1
2
db.book.find({"author": "James"}, 
    {"_id": 1, "title": 1, "author": 1})

分页查询

1
2
3
db.book.find({})
    .sort({"viewCount" : -1})
    .skip(10).limit(5)

这种基于BSON/JSON 的语法格式并不复杂,它的表达能力或许要比SQL更加强大。 与 MongoDB 做法类似的还有 ElasticSearch,后者是搜索数据库的佼佼者。

关于文档操作与 SQL方式完整的对比,官方的文档描述得比较详细: https://docs.mongodb.com/manual/reference/sql-comparison/

索引

索引是一个数据库的关键能力,MongoDB 支持非常丰富的索引类型。 利用这些索引,可以实现快速的数据查找,而索引的类型和特性则是针对不同的应用场景设计的。

索引的技术实现依赖于底层的存储引擎,在当前的版本中 MongoDB 使用 wiredTiger 作为默认的引擎。 在索引的实现上使用了 B+树的结构,这与其他的传统数据库并没有什么不同。

关于wiredTiger存储引擎介绍

使用 ensureIndexes 可以为集合声明一个普通的索引:

1
db.book.ensureIndex({author: 1})
author后面的数字 1 代表升序,如果是降序则是 -1

实现复合式(compound)的索引,如下:

1
db.book.ensureIndex({type: 1, published: 1})
只有对于复合式索引时,索引键的顺序才变得有意义

如果索引的字段是数组类型,该索引就自动成为数组(multikey)索引:

1
db.book.ensureIndex({tags: 1})
MongoDB 可以在复合索引上包含数组的字段,但最多只能包含一个

索引特性

在声明索引时,还可以通过一些参数化选项来为索引赋予一定的特性,包括:

  • unique=true,表示一个唯一性索引
  • expireAfterSeconds=3600,表示这是一个TTL索引,并且数据将在1小时后老化
  • sparse=true,表示稀疏的索引,仅索引非空(non-null)字段的文档
  • partialFilterExpression: { rating: { $gt: 5 },条件式索引,即满足计算条件的文档才进行索引

索引分类

除了普通索引之外,MongoDB 支持的类型还包括:

  • 哈希(HASH)索引,哈希是另一种快速检索的数据结构,MongoDB 的 HASH 类型分片键会使用哈希索引。
  • 地理空间索引,用于支持快速的地理空间查询,如寻找附近1公里的商家。
  • 文本索引,用于支持快速的全文检索
  • 模糊索引(Wildcard Index),一种基于匹配规则的灵活式索引,在4.2版本开始引入。

索引评估、调优

使用 explain() 命令可以用于查询计划分析,进一步评估索引的效果。

1
db.test.explain().find( { a : 5 } )

从结果 winningPlan 中可以看出执行计划是否高效,比如:

  • 未能命中索引的结果,会显示COLLSCAN
  • 命中索引的结果,使用IXSCAN
  • 出现了内存排序,显示为 SORT

关于 explain 的结果说明,可以进一步参考文档: https://docs.mongodb.com/manual/reference/explain-results/index.html

集群

架构说明

  • 数据分片(Shards) 分片用于存储真正的集群数据,可以是一个单独的 Mongod实例,也可以是一个副本集。 生产环境下Shard一般是一个 Replica Set,以防止该数据片的单点故障。 对于分片集合(sharded collection)来说,每个分片上都存储了集合的一部分数据(按照分片键切分),如果集合没有分片,那么该集合的数据都存储在数据库的 Primary Shard中。
  • 配置服务器(Config Servers) 保存集群的元数据(metadata),包含各个Shard的路由规则,配置服务器由一个副本集(ReplicaSet)组成。
  • 查询路由(Query Routers) Mongos是 Sharded Cluster 的访问入口,其本身并不持久化数据 。Mongos启动后,会从 Config Server 加载元数据,开始提供服务,并将用户的请求正确路由到对应的Shard。 Sharding 集群可以部署多个 Mongos 以分担客户端请求的压力。

Sharded Cluster Components

MongoDB 客户端图形工具

Compass 是一种用于查询、优化和分析 MongoDB 数据的免费交互式工具。获取关键见解,拖放以构建管道等。

在 Compass 中轻松处理您的数据,Compass 是由 MongoDB 构建并用于 MongoDB 的图形用户界面。Compass 在单个集中式界面中提供模式分析、索引优化和聚合管道等所有功能。

  • Compass 可免费下载和使用
  • 适用于 Linux、Mac 和 Windows

在Docker中快速启动MongoDB

Install MongoDB Community with Docker

  1. Pull the MongoDB Docker Image
1
docker pull mongodb/mongodb-community-server:latest
  1. Run the Image as a Container
1
docker run --name mongodb -p 27017:27017 -d mongodb/mongodb-community-server:latest

Deploying a MongoDB Cluster with Docker

  1. Create a Docker Network
1
docker network create mongoCluster
  1. Start MongoDB Instances
1
docker run -d --rm -p 27017:27017 --name mongo1 --network mongoCluster mongo:5 mongod --replSet myReplicaSet --bind_ip localhost,mongo1

Start two other containers

1
2
3
docker run -d --rm -p 27018:27017 --name mongo2 --network mongoCluster mongo:5 mongod --replSet myReplicaSet --bind_ip localhost,mongo2
 
docker run -d --rm -p 27019:27017 --name mongo3 --network mongoCluster mongo:5 mongod --replSet myReplicaSet --bind_ip localhost,mongo3
  1. Initiate the Replica Set
1
2
3
4
5
6
7
8
docker exec -it mongo1 mongosh --eval "rs.initiate({
 _id: \"myReplicaSet\",
 members: [
   {_id: 0, host: \"mongo1\"},
   {_id: 1, host: \"mongo2\"},
   {_id: 2, host: \"mongo3\"}
 ]
})"
  1. Test and Verify the Replica Set
1
docker exec -it mongo1 mongosh --eval "rs.status()"