Mongodb入门介绍

发布于:2025-08-08 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、介绍

MongoDB 是一个文档型数据库,数据以类似 JSON 的文档形式存储。

MongoDB 的设计理念是为了应对大数据量、高性能和灵活性需求。

MongoDB使用集合(Collections)来组织文档(Documents),每个文档都是由键值对组成的。

  • 数据库(Database):存储数据的容器,类似于关系型数据库中的数据库。
  • 集合(Collection):数据库中的一个集合,类似于关系型数据库中的表。
  • 文档(Document):集合中的一个数据记录,类似于关系型数据库中的行(row),以 BSON 格式存储。

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成,文档类似于 JSON 对象,字段值可以包含其他文档,数组及文档数组:

二、安装

1、window系统安装

(1)安装mongodb

最新版本的 MongoDB 提供了可用于 64 位系统的预编译二进制包,你可以从 MongoDB 官网下载安装,MongoDB 预编译二进制包下载地址:Download MongoDB Community Server | MongoDB

下载 .msi 文件,下载后双击该文件,按操作提示安装即可。

点击 "Next" 按钮来启动安装过程:

接下来,将出现一个协议窗口,选中同意的选项,然后再点击 "Next" 按钮:

现在,出现了两个选择:您可以以网络服务用户身份运行 MongoDB,也可以以本地或域用户身份运行它。

如果您需要简单性和基本功能,网络服务用户选项就可以了,如果您需要对权限进行更多控制,或者需要使用特定用户凭据访问和限制资源,则选择本地或域用户选项会更合适。

我们简单测试就选第一个,然后单击"Next" 按钮:

接下来我们可以选择完整安装,改安装方式默认配置安装所有 MongoDB 组件和工具,当然你也可以选择自定义安装。

选择安装方法后,您需要单击 "Install" 按钮来开始安装过程:

安装完成后,点击 "Finish" 按钮关闭安装程序:

设置环境变量:系统属性->环境变量->系统变量->路径->编辑环境变量:

(2)配置 MongoDB 服务

创建配置文件

创建一个配置文件。该文件必须设置 systemLog.path 参数,包括一些附加的配置选项更好。

例如,创建一个配置文件位于 D:\tools\mongodb\mongod.cfg,其中指定 systemLog.path 和 storage.dbPath。具体配置内容如下:

systemLog:
    destination: file
    path: c:\data\log\mongod.log
storage:
    dbPath: c:\data\db

安装 MongoDB服务

通过执行 mongod,使用 --install 选项来安装服务,使用 --config 选项来指定之前创建的配置文件。

mongod  --config "D:\tools\mongodb\mongod.cfg" --install

要使用备用 dbpath,可以在配置文件(例如:D:\tools\mongodb\mongod.cfg)或命令行中通过 --dbpath 选项指定。

如果需要,您可以安装 mongod 或 mongos 的多个实例的服务。只需要通过使用 --serviceName 和 --serviceDisplayName 指定不同的实例名。只有当存在足够的系统资源和系统的设计需要这么做。

启动 MongoDB 服务

net start MongoDB

关闭 MongoDB 服务

net stop MongoDB

移除 MongoDB 服务

mongod --remove

(3)交互工具MongoDB Shell安装

MongoDB Shell 是 MongoDB 提供的官方交互式界面,允许用户与 MongoDB 数据库进行交互、执行命令和操作数据库。

MongoDB Shell 是基于 JavaScript 的,允许用户直接在命令行或者脚本中使用 JavaScript 语言来操作 MongoDB 数据库。

从 MongoDB 官网下载适用于 windows的 MongoDB Shell,下载地址 MongoDB Shell Download | MongoDB :

下载完成后是压缩包,进行解压缩。同时进行配置环境变量,这样可以在命令行中直接运行 mongosh 命令来启动 MongoDB Shell。

启动 MongoDB Shell:

在命令行中输入 mongosh 命令,启动 MongoDB Shell,如果 MongoDB 服务器运行在本地默认端口(27017),则可以直接连接。

mongosh

查看版本:

mongosh --version
2.2.9

连接到 MongoDB 服务器:

如果 MongoDB 服务器运行在非默认端口或者远程服务器上,可以使用以下命令连接:

mongosh --host <hostname>:<port>

其中 <hostname> 是 MongoDB 服务器的主机名或 IP 地址,<port> 是 MongoDB 服务器的端口号。

执行基本操作:

连接成功后,可以执行各种 MongoDB 数据库操作。例如:

  • 查看当前数据库:db
  • 显示数据库列表:show dbs
  • 切换到指定数据库:use <database_name>
  • 执行查询操作:db.<collection_name>.find()
  • 插入文档:db.<collection_name>.insertOne({ ... })
  • 更新文档:db.<collection_name>.updateOne({ ... })
  • 删除文档:db.<collection_name>.deleteOne({ ... })
  • 退出 MongoDB Shell:quit() 或者 exit

实例

以下是使用 MongoDB Shell 连接到本地 MongoDB 服务器,并执行一些基本操作的示例:

实例

# 启动 MongoDB Shell
mongosh

# 连接到本地 MongoDB 服务器
test> show dbs
admin   40.00 KiB
config  72.00 KiB
local   40.00 KiB
bolong  72.00 KiB
test> use bolong
switched to db bolong

# 插入文档
bolong> db.mycollection.insertOne({ name: "Alice", age: 30 })
{
  acknowledged: true,
  insertedId: ObjectId('667cd8789a69705686ed70f2')
}


# 查询文档
bolong> db.mycollection.find()
[
  { _id: ObjectId('667cd8789a69705686ed70f2'), name: 'Alice', age: 30 }
]

# 更新文档
bolong> db.mycollection.updateOne({ name: "Alice" }, { $set: { age: 31 } })
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}

# 删除文档
bolong> db.mycollection.deleteOne({ name: "Alice" })
{ acknowledged: true, deletedCount: 1 }

# 退出 MongoDB Shell
bolong> quit()

通过上述步骤和示例,你可以开始使用 MongoDB Shell 来管理和操作 MongoDB 数据库。

2、Linux平台安装MongoDB

(1)下载安装包

MongoDB 提供了 linux 各个发行版本 64 位的安装包,你可以在官网下载安装包。

安装前我们需要安装各个 Linux 平台依赖包。

Red Hat/CentOS:

sudo yum install libcurl openssl

Ubuntu 18.04 LTS ("Bionic")/Debian 10 "Buster":

sudo apt-get install libcurl4 openssl

Ubuntu 16.04 LTS ("Xenial")/Debian 9 "Stretch":

sudo apt-get install libcurl3 openssl

MongoDB 源码下载地址:Download MongoDB Community Server | MongoDB

这里我们选择 tgz 下载,下载完安装包,并解压 tgz(以下演示的是 64 位 Linux上的安装) 。

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-4.2.8.tgz    # 下载
tar -zxvf mongodb-linux-x86_64-ubuntu1604-4.2.8.tgz                                    # 解压

mv mongodb-src-r4.2.8  /usr/local/mongodb                          # 将解压包拷贝到指定目录

MongoDB 的可执行文件位于 bin 目录下,所以可以将其添加到 PATH 路径中,如本文的 /usr/local/mongodb 。

export PATH=/usr/local/mongodb/bin:$PATH

(2)创建数据库目录

默认情况下 MongoDB 启动后会初始化以下两个目录:

  • 数据存储目录:/var/lib/mongodb
  • 日志文件目录:/var/log/mongodb

我们在启动前可以先创建这两个目录并设置当前用户有读写权限:

sudo mkdir -p /var/lib/mongo
sudo mkdir -p /var/log/mongodb
sudo chown `whoami` /var/lib/mongo     # 设置权限
sudo chown `whoami` /var/log/mongodb   # 设置权限

接下来启动 Mongodb 服务:

mongod --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork

打开 /var/log/mongodb/mongod.log 文件看到以下信息,说明启动成功。

# tail -10f /var/log/mongodb/mongod.log
2020-07-09T12:20:17.391+0800 I  NETWORK  [listener] Listening on /tmp/mongodb-27017.sock
2020-07-09T12:20:17.392+0800 I  NETWORK  [listener] Listening on 127.0.0.1
2020-07-09T12:20:17.392+0800 I  NETWORK  [listener] waiting for connections on port 27017

三、MongoDB 概念解析

SQL 术语/概念 MongoDB 术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键

完整术语列表:

  • 文档(Document):MongoDB 的基本数据单元,通常是一个 JSON-like 的结构,可以包含多种数据类型。

  • 集合(Collection):类似于关系型数据库中的表,集合是一组文档的容器。在 MongoDB 中,一个集合中的文档不需要有一个固定的模式。

  • 数据库(Database):包含一个或多个集合的 MongoDB 实例。

  • BSON:Binary JSON 的缩写,是 MongoDB 用来存储和传输文档的二进制形式的 JSON。

  • 索引(Index):用于优化查询性能的数据结构,可以基于集合中的一个或多个字段创建索引。

  • 分片(Sharding):一种分布数据到多个服务器(称为分片)的方法,用于处理大数据集和高吞吐量应用。

  • 副本集(Replica Set):一组维护相同数据集的 MongoDB 服务器,提供数据的冗余备份和高可用性。

  • 主节点(Primary):副本集中负责处理所有写入操作的服务器。

  • 从节点(Secondary):副本集中的服务器,用于读取数据和在主节点故障时接管为主节点。

  • MongoDB Shell:MongoDB 提供的命令行界面,用于与 MongoDB 实例交互。

  • 聚合框架(Aggregation Framework):用于执行复杂的数据处理和聚合操作的一系列操作。

  • Map-Reduce:一种编程模型,用于处理大量数据集的并行计算。

  • GridFS:用于存储和检索大于 BSON 文档大小限制的文件的规范。

  • ObjectId:MongoDB 为每个文档自动生成的唯一标识符。

  • CRUD 操作:创建(Create)、读取(Read)、更新(Update)、删除(Delete)操作。

  • 事务(Transactions):从 MongoDB 4.0 开始支持,允许一组操作作为一个原子单元执行。

  • 操作符(Operators):用于查询和更新文档的特殊字段。

  • 连接(Join):MongoDB 允许在查询中使用 $lookup 操作符来实现类似 SQL 的连接操作。

  • TTL(Time-To-Live):可以为集合中的某些字段设置 TTL,以自动删除旧数据。

  • 存储引擎(Storage Engine):MongoDB 用于数据存储和管理的底层技术,如 WiredTiger 和 MongoDB 的旧存储引擎 MMAPv1。

  • MongoDB Compass:MongoDB 的图形界面工具,用于可视化和管理 MongoDB 数据。

  • MongoDB Atlas:MongoDB 提供的云服务,允许在云中托管 MongoDB 数据库。

MongoDB 数据类型

下表为MongoDB中常用的几种数据类型。

数据类型 描述
String 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean 布尔值。用于存储布尔值(真/假)。
Double 双精度浮点值。用于存储浮点值。
Min/Max keys 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Array 用于将数组或列表或多个值存储为一个键。
Timestamp 时间戳。记录文档修改或添加的具体时间。
Object 用于内嵌文档。
Null 用于创建空值。
Symbol 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID 对象 ID。用于创建文档的 ID。
Binary Data 二进制数据。用于存储二进制数据。
Code 代码类型。用于在文档中存储 JavaScript 代码。
Regular expression 正则表达式类型。用于存储正则表达式。

四、MongoDB 用户管理

在 MongoDB 中进行用户管理涉及用户的创建、分配角色、认证和登录等操作。

下面是一个详细的说明,包含如何使用 MongoDB Shell (mongo) 或 MongoDB Compass 来管理用户。

使用 MongoDB Shell (mongo) 管理用户

以下是使用 MongoDB Shell (mongosh) 进行用户管理的详细说明,包括创建用户、分配角色、认证和登录的具体步骤。

1. 连接到 MongoDB

首先,打开你的终端并使用 mongosh 命令连接到 MongoDB 服务器:

mongosh --host <hostname> --port <port>

说明:

  • mongosh:启动 MongoDB Shell 命令行工具。
  • --host <hostname>:指定 MongoDB 服务器的主机名或 IP 地址。
    • <hostname>:MongoDB 服务器的主机名(如 localhost)或 IP 地址(如 127.0.0.1)。
  • --port <port>:指定 MongoDB 服务器的端口号。
    • <port>:MongoDB 服务器监听的端口号,默认端口是 27017

2. 切换到目标数据库

在 MongoDB 中,用户是针对特定数据库创建的,使用 use 命令切换到你要创建用户的数据库:

use <database_name>
  • database_name - 为要切换的数据库。

3. 创建用户

使用 db.createUser 命令创建用户并分配角色。

例如,创建一个名为 testuser 的用户,密码为 password123,并赋予 readWrite 和 dbAdmin 角色:

db.createUser({
  user: "testuser",
  pwd: "password123",
  roles: [
    { role: "readWrite", db: "<database_name>" },
    { role: "dbAdmin", db: "<database_name>" }
  ]
})

4. 验证用户

创建用户后,你可以使用 db.auth 命令验证用户身份:

db.auth("testuser", "password123")

5. 启用身份验证

为了确保只有经过身份验证的用户才能访问 MongoDB,需要启用身份验证。

编辑 MongoDB 配置文件 mongod.conf,并在其中添加以下内容:

security:
  authorization: "enabled"

然后重启 MongoDB 服务以应用更改。

6. 使用用户身份登录

启用身份验证后,你需要使用创建的用户身份连接到 MongoDB:

mongosh --host <hostname> --port <port> -u "testuser" -p "password123" --authenticationDatabase "<database_name>"

7. 删除用户

使用 db.dropUser 命令删除指定用户。

例如,删除名为 testuser 的用户:

db.dropUser("testuser")

实例操作

以下是一个完整的示例操作流程:

启动 MongoDB Shell 并连接到服务器:

mongosh --host localhost --port 27017

切换到 testdb 数据库:

use testdb

创建 testuser 用户:

db.createUser({
  user: "testuser",
  pwd: "password123",
  roles: [{ role: "readWrite", db: "testdb" }]
})

启用身份验证并重启 MongoDB 实例

编辑 mongod.conf 文件,添加以下内容:

security:
  authorization: "enabled"

重启 MongoDB 服务:

sudo systemctl restart mongod

使用 testuser 用户进行身份验证连接:

mongosh --host localhost --port 27017 -u "testuser" -p "password123" --authenticationDatabase "testdb"

删除 testuser 用户:

db.dropUser("testuser")

五、MongoDB 连接

标准 URI 连接语法:

mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
  • mongodb://:协议头,表示使用 MongoDB。
  • [username:password@]:(可选)认证信息,包括用户名和密码。
  • host1[:port1][,...hostN[:portN]]:服务器地址和端口,可以是一个或多个 MongoDB 服务器的地址和端口。
  • /[defaultauthdb]:(可选)默认认证数据库。
  • [?options]:(可选)连接选项。

标准的连接格式包含了多个选项(options),如下所示:

  • authSource:指定认证数据库。
  • replicaSet:指定副本集的名称。
  • ssl:启用 SSL 连接(true 或 false)。
  • readPreference:指定读偏好,如 primaryprimaryPreferredsecondarysecondaryPreferrednearest
  • connectTimeoutMS:指定连接超时时间(毫秒)。
  • socketTimeoutMS:指定套接字超时时间(毫秒)。

连接到本地 MongoDB 实例(默认端口 27017):

mongodb://localhost

连接到本地 MongoDB 实例,指定数据库:

mongodb://localhost/mydatabase

使用用户名和密码连接到本地 MongoDB 实例:

mongodb://username:password@localhost/mydatabase

连接到远程 MongoDB 实例:

mongodb://remotehost:27017

连接到副本集(Replica Set):

mongodb://host1:27017,host2:27017,host3:27017/mydatabase?replicaSet=myReplicaSet

使用 SSL 连接到 MongoDB:

mongodb://username:password@localhost:27017/mydatabase?ssl=true

使用多个选项连接:

mongodb://username:password@localhost:27017/mydatabase?authSource=admin&ssl=true

六、MongoDB 创建数据库

在MongoDB中,数据库的创建是一个简单的过程,当你首次向MongoDB中插入数据时,如果数据库不存在,MongoDB会自动创建它。

我们只需选择一个数据库名称,并开始向其中插入文档即可。

语法

当你使用 use 命令来指定一个数据库时,如果该数据库不存在,MongoDB将自动创建它。

MongoDB 创建数据库的语法格式如下:

use DATABASE_NAME

如果数据库不存在,则创建数据库,否则切换到指定数据库。

实例

以下实例我们创建了数据库 bolong:

> use bolong
switched to db bolong
> db
bolong

执行 use bolong命令后,MongoDB 将创建名为 bolong 的新数据库。此时,你可以开始在这个数据库中创建集合和插入文档。

如果你想查看所有数据库,可以使用 show dbs 命令:

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
> 

可以看到,我们刚创建的数据库 bolong并不在数据库的列表中, 要显示它,我们需要向 runoob 数据库插入一些数据。

> db.runoob.insertOne({"name":"柏龙"})
WriteResult({ "nInserted" : 1 })
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
bolong  0.000GB

创建集合

创建数据库后,通常需要在其中创建集合(collections),以存储文档(documents)。

集合类似于关系数据库中的表,以下是创建集合的步骤:

使用 use 命令指定数据库。

使用 db.createCollection() 方法创建集合。

实例

use myNewDatabase
db.createCollection("myNewCollection")

上述命令将在 myNewDatabase 数据库中创建一个名为 myNewCollection 的新集合。

查看数据库列表

要查看当前 MongoDB 实例中所有数据库的列表,可以使用 show dbs 命令:

show dbs

查看当前数据库

要查看当前正在使用的数据库,可以使用 db 命令:

db

删除数据库

如果你需要删除数据库,可以使用 db.dropDatabase() 方法:

use myDatabase
db.dropDatabase()

上述命令将删除当前正在使用的 myDatabase 数据库及其所有集合。

默认数据库

MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。

当您通过 shell 连接到 MongoDB 实例时,如果未使用 use 命令切换到其他数据库,则会默认使用 test 数据库。

例如,在启动 MongoDB 实例并连接到 MongoDB shell 后,如果您开始插入文档而未显式指定数据库,MongoDB 将默认使用 test 数据库。

实例

use test
db.myCollection.insertOne({ name: "Alice", age: 30 })

在这个例子中,如果 test 数据库不存在,则 MongoDB 将自动创建它。

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

七、MongoDB 删除数据库

语法

MongoDB 删除数据库的语法格式如下:

db.dropDatabase()

删除当前数据库,默认为 test,你可以使用 db 命令查看当前数据库名。

实例

以下实例我们删除了数据库 bolong。

首先,查看所有数据库:

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
bolong  0.000GB

接下来我们切换到数据库 bolong:

> use bolong
switched to db bolong
> 

执行删除命令:

> db.dropDatabase()
{ "dropped" : "bolong", "ok" : 1 }

最后,我们再通过 show dbs 命令数据库是否删除成功:

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

删除集合

集合删除语法格式如下:

db.collection.drop()

以下实例删除了 runoob 数据库中的集合 site:

> use bolong
switched to db bolong
> db.createCollection("bolong")     # 先创建集合,类似数据库中的表
> show tables             # show collections 命令会更加准确点
bolong
> db.bolong.drop()
true
> show tables

八、MongoDB 创建集合

MongoDB 中使用 createCollection() 方法来创建集合。

语法格式:

db.createCollection(name, options)

参数说明:

  • name: 要创建的集合名称。
  • options: 可选参数, 指定有关内存大小及索引的选项。

options 可以是如下参数:

参数名 类型 描述 示例值
capped 布尔值 是否创建一个固定大小的集合。 true
size 数值 集合的最大大小(以字节为单位)。仅在 capped 为 true 时有效。 10485760 (10MB)
max 数值 集合中允许的最大文档数。仅在 capped 为 true 时有效。 5000
validator 对象 用于文档验证的表达式。 { $jsonSchema: { ... }}
validationLevel 字符串 指定文档验证的严格程度。
"off":不进行验证。
"strict":插入和更新操作都必须通过验证(默认)。
"moderate":仅现有文档更新时必须通过验证,插入新文档时不需要。
"strict"
validationAction 字符串 指定文档验证失败时的操作。
"error":阻止插入或更新(默认)。
"warn":允许插入或更新,但会发出警告。
"error"
storageEngine 对象 为集合指定存储引擎配置。 { wiredTiger: { ... }}
collation 对象 指定集合的默认排序规则。 { locale: "en", strength: 2 }

在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。

使用这些选项创建一个集合的实例:

实例

db.createCollection("myComplexCollection", {
  capped: true,
  size: 10485760,
  max: 5000,
  validator: { $jsonSchema: {
    bsonType: "object",
    required: ["name", "email"],
    properties: {
      name: {
        bsonType: "string",
        description: "必须为字符串且为必填项"
      },
      email: {
        bsonType: "string",
        pattern: "^.+@.+$",
        description: "必须为有效的电子邮件地址"
      }
    }
  }},
  validationLevel: "strict",
  validationAction: "error",
  storageEngine: {
    wiredTiger: { configString: "block_compressor=zstd" }
  },
  collation: { locale: "en", strength: 2 }
});

这个例子创建了一个集合,具有以下特性:

  • 固定大小,最大 10MB,最多存储 5000 个文档。
  • 文档必须包含 name 和 email 字段,其中 name 必须是字符串,email 必须是有效的电子邮件格式。
  • 验证级别为严格,验证失败将阻止插入或更新。
  • 使用 WiredTiger 存储引擎,指定块压缩器为 zstd。
  • 默认使用英语排序规则。

实例

在 test 数据库中创建 bolong 集合:

> use test
switched to db test
> db.createCollection("bolong")
{ "ok" : 1 }
>

如果要查看已有集合,可以使用 show collections 或 show tables 命令:

> show collections
runoob
system.indexes

下面是带有几个关键参数的 createCollection() 的用法:

创建了一个固定大小的集合,最大大小为 5MB(5242880 字节),最多存储 5000 个文档。

db.createCollection("myCappedCollection", { capped: true, size: 5242880, max: 5000 });

在 MongoDB 中,你不需要创建集合,当你插入一些文档时,MongoDB 会自动创建集合。

> db.mycol2.insert({"name" : "柏龙"})
> show collections
mycol2
...

创建了一个最大大小为 1MB(1048576 字节)的固定大小集合:

db.createCollection("myCappedCollection", { capped: true, size: 1048576 });

以下例子为 myCollection 集合创建了一个验证器,要求文档中必须有 name 和 age 字段,且 name 必须是字符串,age 必须是非负整数。

实例

db.createCollection("myCollection", {
  validator: { $jsonSchema: {
    bsonType: "object",
    required: ["name", "age"],
    properties: {
      name: {
        bsonType: "string",
        description: "必须为字符串且为必填项"
      },
      age: {
        bsonType: "int",
        minimum: 0,
        description: "必须为整数且为必填项"
      }
    }
  }}
});

九、MongoDB 更新集合名

MongoDB 可以使用 renameCollection 方法来来重命名集合。

renameCollection 方法在 MongoDB 的 admin 数据库中运行,可以将一个集合重命名为另一个名称。

renameCollection 命令的语法:

db.adminCommand({
  renameCollection: "sourceDb.sourceCollection",
  to: "targetDb.targetCollection",
  dropTarget: <boolean>
})

参数说明:

  • renameCollection:要重命名的集合的完全限定名称(包括数据库名)。
  • to:目标集合的完全限定名称(包括数据库名)。
  • dropTarget(可选):布尔值。如果目标集合已经存在,是否删除目标集合。默认值为 false

实例

假设你要将 test 数据库中的 oldCollection 重命名为 newCollection,可以按以下步骤进行:

1. 确保已连接到 test 数据库

use test

2. 运行 renameCollection 命令

db.adminCommand({ 
  renameCollection: "test.oldCollection", 
  to: "test.newCollection" 
});

如果你要将集合重命名到另一个数据库,例如将 test 数据库中的 oldCollection 重命名为 production 数据库中的 newCollection,可以这样做:

db.adminCommand({ 
  renameCollection: "test.oldCollection", 
  to: "production.newCollection" 
});

注意事项

  • 权限要求:执行 renameCollection 命令需要具有对源数据库和目标数据库的适当权限。通常需要 dbAdmin 或 dbOwner 角色。

  • 目标集合不存在:目标集合不能已经存在。如果目标集合存在,则会返回错误。

  • 索引和数据:重命名集合会保留所有文档和索引。

检查重命名结果

重命名后,可以通过以下命令检查新的集合是否存在:

use test
show collections

如果集合已重命名为 newCollection,你应该会在结果中看到 newCollection。

处理重命名失败的情况

如果重命名过程中发生错误,你可以根据错误消息采取相应的措施。例如,如果目标集合已经存在,可以先删除目标集合(如果确认不需要),然后重新执行重命名操作:

实例

use production
db.newCollection.drop();

use test
db.adminCommand({
  renameCollection: "test.oldCollection",
  to: "production.newCollection"
});

通过 renameCollection 方法,你可以有效地管理 MongoDB 集合的名称,确保数据库结构符合应用需求。

十、MongoDB 删除集合

MongoDB 中使用 drop() 方法来删除集合。

drop() 方法可以永久地从数据库中删除指定的集合及其所有文档,这是一个不可逆的操作,因此需要谨慎使用。

语法格式:

db.collection.drop()

返回值

如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。

实例

在数据库 mydb 中,我们可以先通过 show collections 命令查看已存在的集合:

>use mydb
switched to db mydb
>show collections
mycol
mycol2
system.indexes
bolong
>

接着删除集合 mycol2 :

>db.mycol2.drop()
true
>

通过 show collections 再次查看数据库 mydb 中的集合:

>show collections
mycol
system.indexes
runoob
>

从结果中可以看出 mycol2 集合已被删除。

十一、MongoDB 插入文档

方法 用途 是否弃用
insertOne() 插入单个文档
insertMany() 插入多个文档

1、insertOne()

insertOne() 方法用于在集合中插入单个文档。

db.collection.insertOne(document, options)
  • document:要插入的单个文档。
  • options(可选):一个可选参数对象,可以包含 writeConcern 和 bypassDocumentValidation 等。

实例

db.myCollection.insertOne({
    name: "Alice",
    age: 25,
    city: "New York"
});

返回结果:

{
    "acknowledged": true,
    "insertedId": ObjectId("60c72b2f9b1d8b5a5f8e2b2d")
}

2、insertMany()

insertMany() 方法用于在集合中插入多个文档。

db.collection.insertMany(documents, options)
  • documents:要插入的文档数组。
  • options(可选):一个可选参数对象,可以包含 ordered、writeConcern 和 bypassDocumentValidation 等。
db.myCollection.insertMany([
    { name: "Bob", age: 30, city: "Los Angeles" },
    { name: "Charlie", age: 35, city: "Chicago" }
]);

返回结果:

{
    "acknowledged": true,
    "insertedIds": [
        ObjectId("60c72b2f9b1d8b5a5f8e2b2e"),
        ObjectId("60c72b2f9b1d8b5a5f8e2b2f")
    ]
}

批量插入的性能优化

如果需要插入大量文档,可以使用 insertMany() 并启用 ordered: false 选项,以提高插入性能。

语法:

db.collection.insertMany([document1, document2, ...], { ordered: false })

参数:

  • ordered: false:表示无序插入,即使某个文档插入失败,也不会影响其他文档的插入。

实例

db.users.insertMany([
  { name: "Henry", age: 60 },
  { name: "Ivy", age: 65 }
], { ordered: false });

插入时的验证

MongoDB 会根据集合的 schema 验证规则(如果定义了)对插入的文档进行验证。如果文档不符合规则,插入操作会失败。

假设集合 users 有一个验证规则,要求 age 字段必须大于 0:

db.createCollection("users", {
  validator: {
    age: { $gt: 0 }
  }
});

如果插入以下文档会失败:

db.users.insertOne({ name: "John", age: -5 }); // 验证失败

十二、MongoDB 更新文档

在 MongoDB 中,更新文档的操作可以使用多种方法实现,常用的方法包括 updateOne()、updateMany()、replaceOne() 和 findOneAndUpdate()

1、updateOne()

updateOne() 方法用于更新匹配过滤器的单个文档。

语法:

db.collection.updateOne(filter, update, options)
  • filter:用于查找文档的查询条件。
  • update:指定更新操作的文档或更新操作符。
  • options:可选参数对象,如 upsertarrayFilters 等。

实例

db.myCollection.updateOne(
    { name: "Alice" },                // 过滤条件
    { $set: { age: 26 } },            // 更新操作
    { upsert: false }                 // 可选参数
);

2、updateMany()

updateMany() 方法用于更新所有匹配过滤器的文档。

语法:

db.collection.updateMany(filter, update, options)
  • filter:用于查找文档的查询条件。
  • update:指定更新操作的文档或更新操作符。
  • options:可选参数对象,如 upsertarrayFilters 等。

实例

db.myCollection.updateMany(
    { age: { $lt: 30 } },             // 过滤条件
    { $set: { status: "active" } },   // 更新操作
    { upsert: false }                  // 可选参数
);

3、replaceOne()

replaceOne() 方法用于替换匹配过滤器的单个文档,新的文档将完全替换旧的文档。

语法:

db.collection.replaceOne(filter, replacement, options)
  • filter:用于查找文档的查询条件。
  • replacement:新的文档,将替换旧的文档。
  • options:可选参数对象,如 upsert 等。

实例

db.myCollection.replaceOne(
    { name: "Bob" },                  // 过滤条件
    { name: "Bob", age: 31 }          // 新文档
);
 

4、findOneAndUpdate()

findOneAndUpdate() 方法用于查找并更新单个文档,可以选择返回更新前或更新后的文档。

语法:

db.collection.findOneAndUpdate(filter, update, options)
  • filter:用于查找文档的查询条件。
  • update:指定更新操作的文档或更新操作符。
  • options:可选参数对象,如 projectionsortupsertreturnDocument 等。

实例

db.myCollection.findOneAndUpdate(
    { name: "Charlie" },              // 过滤条件
    { $set: { age: 36 } },            // 更新操作
    { returnDocument: "after" }       // 可选参数,返回更新后的文档
);

选项参数

这些更新方法的 options 参数通常可以包含以下选项:

  • upsert:如果没有匹配的文档,是否插入一个新文档。
  • arrayFilters:当更新嵌套数组时,指定应更新的数组元素的条件。
  • collation:指定比较字符串时使用的排序规则。
  • returnDocument:在 findOneAndUpdate 中使用,指定返回更新前 ("before") 或更新后 ("after") 的文档。

简单实例

更新单个文档:

db.myCollection.updateOne(
    { name: "Alice" },
    { $set: { age: 26 } }
);

更新多个文档:

db.myCollection.updateMany(
    { age: { $lt: 30 } },
    { $set: { status: "active" } }
);

替换单个文档:

db.myCollection.replaceOne(
    { name: "Bob" },
    { name: "Bob", age: 31 }
);

查找并更新单个文档:

db.myCollection.findOneAndUpdate(
    { name: "Charlie" },
    { $set: { age: 36 } },
    { returnDocument: "after" }
);

以下实例中我们替换了 _id 为 56064f89ade2f21f36b03136 的文档数据:

>db.col.save({
    "_id" : ObjectId("56064f89ade2f21f36b03136"),
    "title" : "MongoDB",
    "description" : "MongoDB 是一个 Nosql 数据库",
    "by" : "bolong",
    "url" : "http://www.xxxxx.com",
    "tags" : [
            "mongodb",
            "NoSQL"
    ],
    "likes" : 110
})

替换成功后,我们可以通过 find() 命令来查看替换后的数据

>db.col.find().pretty()
{
        "_id" : ObjectId("56064f89ade2f21f36b03136"),
        "title" : "MongoDB",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "bolong",
        "url" : "http://www.xxxxx.com",
        "tags" : [
                "mongodb",
                "NoSQL"
        ],
        "likes" : 110
}
> 

更多实例

只更新第一条记录:

db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } );

全部更新:

db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true );

只添加第一条:

db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} },true,false );

全部添加进去:

db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true );

全部更新:

db.col.update( { "count" : { $gt : 15 } } , { $inc : { "count" : 1} },false,true );

只更新第一条记录:

db.col.update( { "count" : { $gt : 10 } } , { $inc : { "count" : 1} },false,false );

十三、MongoDB 删除文档

常用的删除文档方法包括 deleteOne()、deleteMany() 以及 findOneAndDelete()。

使用场景:

  • 数据清理:删除不再需要的旧数据或无效数据。
  • 数据修正:在数据修正过程中删除错误的或重复的文档。
  • 自动化任务:在自动化脚本或任务中,根据特定条件删除文档。

1、deleteOne()

deleteOne() 方法用于删除匹配过滤器的单个文档。

语法:

db.collection.deleteOne(filter, options)
  • filter:用于查找要删除的文档的查询条件。
  • options(可选):一个可选参数对象。

实例

db.myCollection.deleteOne({ name: "Alice" });

返回结果:

{
    "acknowledged": true,
    "deletedCount": 1
}

2、deleteMany()

deleteMany() 方法用于删除所有匹配过滤器的文档。

语法:

db.collection.deleteMany(filter, options)
  • filter:用于查找要删除的文档的查询条件。
  • options(可选):一个可选参数对象。

实例

db.myCollection.deleteMany({ status: "inactive" });

返回结果:

{
    "acknowledged": true,
    "deletedCount": 1
}

3、findOneAndDelete()

findOneAndDelete() 方法用于查找并删除单个文档,并可以选择返回删除的文档。

语法:

db.collection.findOneAndDelete(filter, options)
  • filter:用于查找要删除的文档的查询条件。
  • options:可选参数对象,如 projectionsort 等。

实例

db.myCollection.findOneAndDelete(
    { name: "Charlie" },
    { projection: { name: 1, age: 1 } }
);

findOneAndDelete 返回被删除的文档,如果找不到匹配的文档,则返回 null。

删除操作的选项

这些删除方法的 options 参数通常可以包含以下选项:

  • writeConcern:指定写操作的确认级别。
  • collation:指定比较字符串时使用的排序规则。
  • projection(仅适用于 findOneAndDelete):指定返回的字段。
  • sort(仅适用于 findOneAndDelete):指定排序顺序以确定要删除的文档。

实例

删除单个文档:

db.myCollection.deleteOne({ name: "Alice" });

删除多个文档:

db.myCollection.deleteMany({ status: "inactive" });

查找并删除单个文档:

db.myCollection.findOneAndDelete(
    { name: "Charlie" },
    { projection: { name: 1, age: 1 } }
);

十四、MongoDB 查询文档

MongoDB 查询文档使用 find()、findOne() 方法。

find() 方法以非结构化的方式来显示所有文档。

语法

MongoDB 查询数据的语法格式如下:

db.collection.find(query, projection)
  • query:用于查找文档的查询条件。默认为 {},即匹配所有文档。
  • projection(可选):指定返回结果中包含或排除的字段。

查找所有文档:

实例

db.myCollection.find();

按条件查找文档:

实例

db.myCollection.find({ age: { $gt: 25 } });

按条件查找文档,并只返回指定字段:

实例

db.myCollection.find(
    { age: { $gt: 25 } },
    { name: 1, age: 1, _id: 0 }
);

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

>db.col.find().pretty()

pretty() 方法以格式化的方式来显示所有文档。

实例

db.col.find().pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "bolong",
        "url" : "http://www.xxxxx.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}

2、findOne()

findOne() 方法用于查找集合中的单个文档。如果找到多个匹配的文档,它只返回第一个。

语法:

db.collection.findOne(query, projection)
  • query:用于查找文档的查询条件。默认为 {},即匹配所有文档。
  • projection(可选):指定返回结果中包含或排除的字段。

查找单个文档:

db.myCollection.findOne({ name: "Alice" });

查找单个文档,并只返回指定字段:

db.myCollection.findOne(
    { name: "Alice" },
    { name: 1, age: 1, _id: 0 }
);

高级查询方法

1、使用比较操作符

MongoDB 支持多种比较操作符,如 $gt、$lt、$gte、$lte、$eq、$ne 等。

查找年龄大于 25 的文档:

db.myCollection.find({ age: { $gt: 25 } });

2、使用逻辑操作符

MongoDB 支持多种逻辑操作符,如 $and、$or、$not、$nor 等。

查找年龄大于 25 且城市为 "New York" 的文档:

实例

db.myCollection.find({
    $and: [
        { age: { $gt: 25 } },
        { city: "New York" }
    ]
});

3、使用正则表达式

可以使用正则表达式进行模式匹配查询。

查找名字以 "A" 开头的文档:

db.myCollection.find({ name: /^A/ });

4、投影

投影用于控制查询结果中返回的字段。可以使用包含字段和排除字段两种方式。

只返回名字和年龄字段:

实例

db.myCollection.find(
    { age: { $gt: 25 } },
    { name: 1, age: 1, _id: 0 }
);

5、排序

可以对查询结果进行排序。

按年龄降序排序:

db.myCollection.find().sort({ age: -1 });

6、限制与跳过

可以对查询结果进行限制和跳过指定数量的文档。

返回前 10 个文档:

db.myCollection.find().limit(10);

跳过前 5 个文档,返回接下来的 10 个文档:

db.myCollection.find().skip(5).limit(10);

实例

查找年龄大于 25 且城市为 "New York" 的文档,只返回名字和年龄字段,按年龄降序排序,并返回前 10 个文档。

实例

db.myCollection.find(
    {
        $and: [
            { age: { $gt: 25 } },
            { city: "New York" }
        ]
    },
    { name: 1, age: 1, _id: 0 }
).sort({ age: -1 }).limit(10);

MongoDB AND 条件

MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。

语法格式如下:

>db.col.find({key1:value1, key2:value2}).pretty()

实例

以下实例通过 by 和 title 键来查询 菜鸟教程 中 MongoDB 教程 的数据

> db.col.find({"by":"bolong", "title":"MongoDB"}).pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "bolong",
        "url" : "http://www.xxxxx.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}

以上实例中类似于 WHERE 语句:WHERE by='bolong' AND title='MongoDB'


MongoDB OR 条件

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

>db.col.find(
   {
      $or: [
         {key1: value1}, {key2:value2}
      ]
   }
).pretty()

实例

以下实例中,我们演示了查询键 by 值为 bolong 或键 title 值为 MongoDB 的文档。

>db.col.find({$or:[{"by":"bolong"},{"title": "MongoDB"}]}).pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "bolong",
        "url" : "http://www.xxxxx.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}
>

AND 和 OR 联合使用

以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: 'where likes>50 AND (by = 'bolong' OR title = 'MongoDB')'

>db.col.find({"likes": {$gt:50}, $or: [{"by": "bolong"},{"title": "MongoDB"}]}).pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "bolong",
        "url" : "http://www.xxxxx.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}

十五、MongoDB 条件操作符

比较操作符

比较操作符有:

操作符 描述 示例
$eq 等于 { age: { $eq: 25 } }
$ne 不等于 { age: { $ne: 25 } }
$gt 大于 { age: { $gt: 25 } }
$gte 大于等于 { age: { $gte: 25 } }
$lt 小于 { age: { $lt: 25 } }
$lte 小于等于 { age: { $lte: 25 } }
$in 在指定的数组中 { age: { $in: [25, 30, 35] } }
$nin 不在指定的数组中 { age: { $nin: [25, 30, 35] } }

$eq (等于)

语法格式:

{ field: { $eq: value } }

查找年龄等于 25 的人:

db.collection.find({ age: { $eq: 25 } })

$ne (不等于)

语法格式:

{ field: { $ne: value } }

查找年龄不等于 25 的人:

db.collection.find({ age: { $ne: 25 } })

$gt (大于)

语法格式:

{ field: { $gt: value } }

查找年龄大于 25 的人:

db.collection.find({ age: { $gt: 25 } })

$gte (大于等于)

语法格式:

{ field: { $gte: value } }

查找年龄大于或等于 25 的人:

db.collection.find({ age: { $gte: 25 } })

$lt (小于)

语法格式:{ field: { $lt: value } }

查找年龄小于 25 的人:

db.collection.find({ age: { $lt: 25 } })

$lte (小于等于)

语法格式:

{ field: { $lte: value } }

查找年龄小于或等于25的人:

db.collection.find({ age: { $lte: 25 } })

$in (值在数组中)

语法格式:

{ field: { $in: [value1, value2, ...] } }

查找年龄在 20、25 和 30 岁之间的人:

db.collection.find({ age: { $in: [20, 25, 30] } })

$nin (值不在数组中)

语法格式:

{ field: { $nin: [value1, value2, ...] } }

查找年龄不在 20、25 和 30 岁之间的人:

db.collection.find({ age: { $nin: [20, 25, 30] } })

逻辑操作符

逻辑操作符有:

操作符 描述 示例
$and 逻辑与,符合所有条件 { $and: [ { age: { $gt: 25 } }, { city: "New York" } ] }
$or 逻辑或,符合任意条件 { $or: [ { age: { $lt: 25 } }, { city: "New York" } ] }
$not 取反,不符合条件 { age: { $not: { $gt: 25 } } }
$nor 逻辑或非,均不符合条件 { $nor: [ { age: { $gt: 25 } }, { city: "New York" } ] }

$and (多个条件都成立)

语法格式:

{ $and: [ { condition1 }, { condition2 } ] }

查找年龄大于 25 且小于 35 的人:

db.collection.find({ $and: [{ age: { $gt: 25 } }, { age: { $lt: 35 } }] })

$or (至少一个条件成立)

语法格式:

{ $or: [ { condition1 }, { condition2 } ] }

查找年龄大于 25 或小于 18 的人:

db.collection.find({ $or: [{ age: { $gt: 25 } }, { age: { $lt: 18 } }] })

$not (取反条件)

语法格式:

{ field: { $not: { condition } } }

查找年龄不大于 25 的人:

db.collection.find({ age: { $not: { $gt: 25 } } })

$nor (没有任何条件成立)

语法格式:

{ $nor: [ { condition1 }, { condition2 } ] }

查找年龄不大于 25 且不小于 18 的人:

db.collection.find({ $nor: [{ age: { $gt: 25 } }, { age: { $lt: 18 } }] })

元素操作符

元素操作符有:

操作符 描述 示例
$exists 字段是否存在 { age: { $exists: true } }
$type 字段的 BSON 类型 { age: { $type: "int" } }

$exists (字段是否存在)

语法格式:

{ field: { $exists: boolean } }

查找包含 age 字段的文档:

db.collection.find({ age: { $exists: true } })

$type (字段类型)

语法格式:

{ field: { $type: "type" } }

查找 age 字段为整数类型的文档:

db.collection.find({ age: { $type: "int" } })

数组操作符

数组操作符有:

操作符 描述 示例
$all 数组包含所有指定的元素 { tags: { $all: ["red", "blue"] } }
$elemMatch 数组中的元素匹配指定条件 { results: { $elemMatch: { score: { $gt: 80, $lt: 85 } } } }
$size 数组的长度等于指定值 { tags: { $size: 3 } }

查找数组 tags 中包含 "red" 和 "blue" 的文档:

db.myCollection.find({ tags: { $all: ["red", "blue"] } });

$all (数组包含指定的所有元素)

语法格式:

{ field: { $all: [value1, value2, ...] } }

查找 tags 数组中包含 "mongodb" 和 "database" 的文档:

db.collection.find({ tags: { $all: ["mongodb", "database"] } })

$elemMatch (数组中至少有一个元素符合条件)

语法格式:

{ field: { $elemMatch: { condition } } }

查找 items 数组中 quantity 大于 10 的元素:

db.collection.find({ items: { $elemMatch: { quantity: { $gt: 10 } } } })

$size (数组的大小)

语法格式:

{ field: { $size: value } }

查找 tags 数组大小为 3 的文档:

db.collection.find({ tags: { $size: 3 } })

其他操作符

还有一些其他操作符如下:

操作符 描述 示例
$regex 匹配正则表达式 { name: { $regex: /^A/ } }
$text 进行文本搜索 { $text: { $search: "coffee" } }
$where 使用 JavaScript 表达式进行条件过滤 { $where: "this.age > 25" }
$near 查找接近指定点的文档 db.collection.find({ location: { $near: [10, 20], $maxDistance: 1000 } })
$geoWithin 查找在指定地理区域内的文档 db.collection.find({ location: { $geoWithin: { $centerSphere: [[10, 20], 1] } } })

$regex (正则表达式匹配)

语法格式:

{ field: { $regex: "pattern" } }

查找 name 以 "John" 开头的文档:

db.collection.find({ name: { $regex: /^John/ } })

$near (接近指定点的文档)

语法格式:

{ field: { $near: [longitude, latitude], $maxDistance: distance } }

查找距离某个位置近的文档:

db.collection.find({ location: { $near: [10, 20], $maxDistance: 1000 } })

$geoWithin (查找指定区域内的文档)

语法格式:

{ field: { $geoWithin: { $centerSphere: [[longitude, latitude], radius] } } }

查找在指定地理区域内的文档:

db.collection.find({ location: { $geoWithin: { $centerSphere: [[10, 20], 1] } } })

十六、MongoDB $type 操作符

$type 操作符用于查询具有指定类型的字段的文档。

MongoDB 的 $type 操作符用于查询字段的 BSON 数据类型。

它允许您指定一个或多个类型,并返回匹配这些类型的文档。

以下是 $type 操作符的详细介绍和示例。

语法:

db.collection.find({ field: { $type: <type> } })
  • field:要检查类型的字段。
  • type:指定的 BSON 类型,可以是类型的数字代码或类型名称的字符串。

BSON 类型

以下是常见的 BSON 类型及其对应的数字代码和字符串名称:

类型代码 类型名称
1 double
2 string
3 object
4 array
5 binData
6 undefined
7 objectId
8 bool
9 date
10 null
11 regex
12 dbPointer
13 javascript
14 symbol
15 javascriptWithScope
16 int
17 timestamp
18 long
19 decimal
255 minKey
127 maxKey

实例

查找字段类型为字符串的文档:

db.myCollection.find({ fieldName: { $type: "string" } })

或使用类型代码:

db.myCollection.find({ fieldName: { $type: 2 } })

查找字段类型为数字的文档,例如,查找 age 字段类型为整数的文档:

db.myCollection.find({ age: { $type: "int" } })

或使用类型代码:

db.myCollection.find({ age: { $type: 16 } })

查找字段类型为布尔值的文档:

db.myCollection.find({ isActive: { $type: "bool" } })

或使用类型代码:

db.myCollection.find({ isActive: { $type: 8 } })

查找字段类型为日期的文档:

db.myCollection.find({ createdAt: { $type: "date" } })

或使用类型代码:

db.myCollection.find({ createdAt: { $type: 9 } })

查找字段类型为多种类型的文档,例如,查找 value 字段类型为字符串或整数的文档:

db.myCollection.find({ value: { $type: ["string", "int"] } })

或使用类型代码:

db.myCollection.find({ value: { $type: [2, 16] } })

查找 details 字段类型为对象,并且 score 字段类型为双精度浮点数的文档:

实例

db.myCollection.find({
    $and: [
        { details: { $type: "object" } },
        { score: { $type: "double" } }
    ]
})

或使用类型代码:

实例

db.myCollection.find({
    $and: [
        { details: { $type: 3 } },
        { score: { $type: 1 } }
    ]
})

通过使用 $type 操作符,您可以精确地查询文档中特定字段的数据类型,从而进行更细粒度的数据过滤和管理。


更多实例

我们使用的数据库名称为"runoob" 我们的集合名称为"col",以下为我们插入的数据。

简单的集合"col":

>db.col.insert({
    title: 'Mongo1', 
    description: 'Mongo',
    by: 'bolong',
    url: 'http://www.xxxxx.com',
    tags: ['Mongo'],
    likes: 200
})
>db.col.insert({title: 'Mongo2', 
    description: 'Mongo',
    by: 'bolong',
    url: 'http://www.xxxxx.com',
    tags: ['Mongo'],
    likes: 150
})
>db.col.insert({title: 'Mongo3', 
    description: 'Mongo',
    by: 'bolong',
    url: 'http://www.xxxxx.com',
    tags: ['Mongo'],
    likes: 100
})

使用find()命令查看数据:

> db.col.find()
{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "Mongo1", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 200 }
{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Mongo2", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 150 }
{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "Mongo3", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 100 }

MongoDB 操作符 - $type 实例

如果想获取 "col" 集合中 title 为 String 的数据,你可以使用以下命令:

db.col.find({"title" : {$type : 2}})
或
db.col.find({"title" : {$type : 'string'}})

输出结果为:

{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "Mongo1", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 200 }
{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Mongo2", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 150 }
{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "Mongo3", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 100 }

十七、MongoDB Limit 与 Skip 方法

MongoDB Limit() 方法

如果你需要在 MongoDB 中读取指定数量的数据记录,可以使用 MongoDB 的 limit() 方法,如果想跳过指定数量的文档读取数据可以使用 skip() 方法。

limit() 方法用于限制查询结果返回的文档数量,而 skip() 方法用于跳过指定数量的文档。这两个方法通常一起使用,可以用来实现分页查询或在大型数据集上进行分批处理。

limit() 方法

limit() 方法用于限制查询结果返回的文档数量。

语法

limit() 方法基本语法如下所示:

db.collection.find().limit(<limit>)
  • <limit>:返回的文档数量。

实例

// 返回前 10 个文档
db.myCollection.find().limit(10);

实例

集合 col 中的数据如下:

{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "Mongo1", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 200 } 
{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Mongo2", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 150 } 
{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "Mongo3", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 100 }

以下实例为显示查询文档中的两条记录:

> db.col.find({},{"title":1,_id:0}).limit(2)
{ "title" : "Mongo1" }
{ "title" : "Mongo2" }
>

注:如果你们没有指定 limit() 方法中的参数则显示集合中的所有数据。


skip() 方法

我们除了可以使用 limit() 方法来读取指定数量的数据外,还可以使用 skip() 方法来跳过指定数量的数据,skip() 方法同样接受一个数字参数作为跳过的记录条数。

skip() 方法用于跳过指定数量的文档,从而实现分页或分批查询。

语法

skip() 方法语法格式如下:

db.collection.find().skip(<skip>)
  • <skip>:要跳过的文档数量。

实例

// 跳过前 10 个文档,返回接下来的 10 个文档
db.myCollection.find().skip(10).limit(10);

实例

以下实例只会显示第二条文档数据

>db.col.find({},{"title":1,_id:0}).limit(1).skip(1)
{ "title" : "Mongo2" }
>

分页查询:

实例

// 第一页,每页 10 个文档
db.myCollection.find().skip(0).limit(10);

// 第二页,每页 10 个文档
db.myCollection.find().skip(10).limit(10);

// 第三页,每页 10 个文档
db.myCollection.find().skip(20).limit(10);

注:skip()方法默认参数为 0 。

注意事项

  • skip() 和 limit() 方法通常用于配合使用,以实现分页查询。但是在大型数据集上使用 skip() 可能会导致性能问题,因为 MongoDB 在执行查询时需要扫描并跳过指定数量的文档,因此建议仅在需要时才使用 skip() 方法,尽量避免在大型数据集上连续使用。
  • 当结合 skip() 和 limit() 时,skip() 应该在 limit() 之前使用,以避免意外行为。

通过使用 limit() 和 skip() 方法,您可以实现在 MongoDB 中对查询结果进行分页处理,提高查询的灵活性和性能。

十八、MongoDB 排序

在 MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。

语法

sort()方法基本语法如下所示:

db.collection.find().sort({ field1: 1, field2: -1 })
  • { field1: 1, field2: -1 }:指定要排序的字段及排序顺序。1 表示升序,-1 表示降序。

实例

按字段升序排序:

实例

// 按 age 字段升序排序
db.myCollection.find().sort({ age: 1 });

按字段降序排序:

实例

// 按 createdAt 字段降序排序
db.myCollection.find().sort({ createdAt: -1 });

可以指定多个字段进行排序,MongoDB 将按照指定的字段顺序依次排序。

实例

// 先按 age 字段升序排序,再按 createdAt 字段降序排序
db.myCollection.find().sort({ age: 1, createdAt: -1 });

col 集合中的数据如下:

{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "Mongo1", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 200 }
{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Mongo2", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 150 }
{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "Mongo3", "description" : "Mongo", "by" : "bolong", "url" : "http://www.xxxxx.com", "tags" : [ "Mongo" ], "likes" : 100 }

以下实例演示了 col 集合中的数据按字段 likes 的降序排列:

>db.col.find({},{"title":1,_id:0}).sort({"likes":-1})
{ "title" : "Mongo1" }
{ "title" : "Mongo2" }
{ "title" : "Mongo3" }
>

注意事项

  • MongoDB 在执行排序时会对查询结果进行排序,因此可能会影响性能,特别是在大型数据集上排序操作可能会较慢。
  • 如果排序字段上有索引,排序操作可能会更高效。在执行频繁的排序操作时,可以考虑创建适当的索引以提高性能。

通过使用 sort() 方法,您可以方便地对 MongoDB 查询结果进行排序,以满足不同排序需求,并根据需要按升序或降序排列文档。

十九、MongoDB 索引

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。

这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可能要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构

在 MongoDB 中,常见的索引类型包括:

  • 单字段索引:基于单个字段的索引。
  • 复合索引:基于多个字段组合的索引。
  • 文本索引:用于支持全文搜索。
  • 地理空间索引:用于地理空间数据的查询。
  • 哈希索引:用于对字段值进行哈希处理的索引。

创建索引

MongoDB 使用 createIndex() 方法来创建索引。

注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(),之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。

语法

createIndex() 方法基本语法格式如下所示:

db.collection.createIndex( keys, options )
  • db:数据库的引用。
  • collection:集合的名称。
  • keys:一个对象,指定了字段名和索引的排序方向(1 表示升序,-1 表示降序)。
  • options:一个可选参数,可以包含索引的额外选项。

options 参数是一个对象,可以包含多种配置选项,以下是一些常用的选项:

  • unique:如果设置为 true,则创建唯一索引,确保索引字段的值在集合中是唯一的。
  • background:如果设置为 true,则索引创建过程在后台运行,不影响其他数据库操作。
  • name:指定索引的名称,如果不指定,MongoDB 会根据索引的字段自动生成一个名称。
  • sparse:如果设置为 true,创建稀疏索引,只索引那些包含索引字段的文档。
  • expireAfterSeconds:设置索引字段的过期时间,MongoDB 将自动删除过期的文档。
  • v:索引版本,通常不需要手动设置。
  • weights:为文本索引指定权重。

实例

// 创建 age 字段的升序索引
db.myCollection.createIndex({ age: 1 });
// 创建 name 字段的文本索引
db.myCollection.createIndex({ name: "text" });

实例

索引创建:

实例

// 创建唯一索引
db.collection.createIndex( { field: 1 }, { unique: true } )

// 创建后台运行的索引
db.collection.createIndex( { field: 1 }, { background: true } )

// 创建稀疏索引
db.collection.createIndex( { field: 1 }, { sparse: true } )

// 创建文本索引并指定权重
db.collection.createIndex( { field: "text" }, { weights: { field: 10 } } )
创建地理空间索引
对于存储地理位置数据的字段,可以使用 2dsphere 或 2d 索引类型来创建地理空间索引。

// 2dsphere 索引,适用于球形地理数据
db.collection.createIndex( { location: "2dsphere" } )

// 2d 索引,适用于平面地理数据
db.collection.createIndex( { location: "2d" } )

创建哈希索引

从 MongoDB 3.2 版本开始,可以使用哈希索引对字段进行哈希,以支持大范围的数值查找。

db.collection.createIndex( { field: "hashed" } )

查看索引

使用 getIndexes() 方法可以查看集合中的所有索引:

db.collection.getIndexes()

删除索引

使用 dropIndex() 或 dropIndexes() 方法可以删除索引:

实例

// 删除指定的索引
db.collection.dropIndex( "indexName" )

// 删除所有索引
db.collection.dropIndexes()

索引策略

在创建索引时,需要考虑以下因素:

  • 查询频率:优先考虑那些经常用于查询的字段。
  • 字段基数:字段值的基数越高(即唯一值越多),索引的效果越好。
  • 索引大小:索引的大小会影响数据库的内存占用和查询性能。

索引优化

在对索引进行优化时,可以考虑以下方法:

  • 选择合适的索引类型:根据查询需求选择合适的索引类型。
  • 创建复合索引:对于经常一起使用的字段,考虑创建复合索引以提高查询效率。
  • 监控索引性能:定期监控索引的使用情况,根据实际需求调整索引。

注意事项

  • 索引虽然可以提高查询性能,但也会增加写操作的开销。因此,在创建索引时需要权衡查询性能和写入性能。
  • 索引会占用额外的存储空间,特别是对于大型数据集,需要考虑索引的存储成本。

通过合理地设计和使用索引,可以大大提高 MongoDB 数据库的查询性能和响应速度,从而更好地支持应用程序的需求。

二十、MongoDB 聚合

MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。

有点类似 SQL 语句中的 count(*)。


aggregate() 方法

MongoDB中聚合的方法使用aggregate()。

语法

aggregate() 方法的基本语法格式如下所示:

>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

实例

集合中的数据如下:

{
   _id: ObjectId(7df78ad8902c)
   title: 'MongoDB Overview', 
   description: 'MongoDB is no sql database',
   by_user: 'bolong1',
   url: 'http://www.xxxxx.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: ObjectId(7df78ad8902d)
   title: 'NoSQL Overview', 
   description: 'No sql database is very fast',
   by_user: 'bolong1',
   url: 'http://www.xxxxx.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 10
},
{
   _id: ObjectId(7df78ad8902e)
   title: 'Neo4j Overview', 
   description: 'Neo4j is no sql database',
   by_user: 'bolong2',
   url: 'http://www.xxxxx.com',
   tags: ['neo4j', 'database', 'NoSQL'],
   likes: 750
},

现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:

> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{
   "result" : [
      {
         "_id" : "bolong1",
         "num_tutorial" : 2
      },
      {
         "_id" : "bolong2",
         "num_tutorial" : 1
      }
   ],
   "ok" : 1
}
>

以上实例类似sql语句:

 select by_user, count(*) from mycol group by by_user

在上面的例子中,我们通过字段 by_user 字段对数据进行分组,并计算 by_user 字段相同值的总和。

下表展示了一些聚合的表达式:

表达式 描述 实例
$sum 计算总和。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avg 计算平均值 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$min 获取集合中所有文档对应值得最小值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$max 获取集合中所有文档对应值得最大值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push 将值加入一个数组中,不会判断是否有重复的值。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first 根据资源文档的排序获取第一个文档数据。 db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$last 根据资源文档的排序获取最后一个文档数据 db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

管道的概念

管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。

MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。

表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。

这里我们介绍一下聚合框架中常用的几个操作:

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。
  • $geoNear:输出接近某一地理位置的有序文档。

管道操作符实例

1、$project实例

db.article.aggregate(
    { $project : {
        title : 1 ,
        author : 1 ,
    }}
 );

这样的话结果中就只还有_id,tilte和author三个字段了,默认情况下_id字段是被包含的,如果要想不包含_id话可以这样:

db.article.aggregate(
    { $project : {
        _id : 0 ,
        title : 1 ,
        author : 1
    }});

2.$match实例

db.articles.aggregate( [
                        { $match : { score : { $gt : 70, $lte : 90 } } },
                        { $group: { _id: null, count: { $sum: 1 } } }
                       ] );

$match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。

3.$skip实例

db.article.aggregate(
    { $skip : 5 });

经过$skip管道操作符处理后,前五个文档被"过滤"掉。

二十一、MongoDB 复制(副本集)

MongoDB复制是将数据同步在多个服务器的过程。

复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。

复制还允许您从硬件故障和服务中断中恢复数据。


什么是复制?

  • 保障数据的安全性
  • 数据高可用性 (24*7)
  • 灾难恢复
  • 无需停机维护(如备份,重建索引,压缩)
  • 分布式读取数据

MongoDB复制原理

mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。

mongodb各个节点常见的搭配方式为:一主一从、一主多从。

主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

MongoDB复制结构图如下所示:

MongoDB复制结构图

以上结构图中,客户端从主节点读取数据,在客户端写入数据到主节点时, 主节点与从节点进行数据交互保障数据的一致性。

副本集特征:

  • N 个节点的集群
  • 任何节点可作为主节点
  • 所有写入操作都在主节点上
  • 自动故障转移
  • 自动恢复

MongoDB副本集设置

在本教程中我们使用同一个MongoDB来做MongoDB主从的实验, 操作步骤如下:

1、关闭正在运行的MongoDB服务器。

现在我们通过指定 --replSet 选项来启动mongoDB。--replSet 基本语法格式如下:

mongod --port "PORT" --dbpath "YOUR_DB_DATA_PATH" --replSet "REPLICA_SET_INSTANCE_NAME"

实例

mongod --port 27017 --dbpath "D:\set up\mongodb\data" --replSet rs0

以上实例会启动一个名为rs0的MongoDB实例,其端口号为27017。

启动后打开命令提示框并连接上mongoDB服务。

在Mongo客户端使用命令rs.initiate()来启动一个新的副本集。

我们可以使用rs.conf()来查看副本集的配置

查看副本集状态使用 rs.status() 命令


副本集添加成员

添加副本集的成员,我们需要使用多台服务器来启动mongo服务。进入Mongo客户端,并使用rs.add()方法来添加副本集的成员。

语法

rs.add() 命令基本语法格式如下:

>rs.add(HOST_NAME:PORT)

实例

假设你已经启动了一个名为mongod1.net,端口号为27017的Mongo服务。 在客户端命令窗口使用rs.add() 命令将其添加到副本集中,命令如下所示:

>rs.add("mongod1.net:27017")
>

MongoDB中你只能通过主节点将Mongo服务添加到副本集中, 判断当前运行的Mongo服务是否为主节点可以使用命令db.isMaster() 。

MongoDB的副本集与我们常见的主从有所不同,主从在主机宕机后所有服务将停止,而副本集在主机宕机后,副本会接管主节点成为主节点,不会出现宕机的情况。

二十二、MongoDB 分片

分片

在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求。

当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。


为什么使用分片

  • 复制所有的写入操作到主节点
  • 延迟的敏感数据会在主节点查询
  • 单个副本集限制在12个节点
  • 当请求量巨大时会出现内存不足。
  • 本地磁盘不足
  • 垂直扩展价格昂贵

MongoDB分片

下图展示了在MongoDB中使用分片集群结构分布:

上图中主要有如下所述三个主要组件:

  • Shard:

    用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障

  • Config Server:

    mongod实例,存储了整个 ClusterMetadata,其中包括 chunk信息。

  • Query Routers:

    前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。


分片实例

分片结构端口分布如下:

Shard Server 1:27020
Shard Server 2:27021
Shard Server 3:27022
Shard Server 4:27023
Config Server :27100
Route Process:40000

步骤一:启动Shard Server

[root@100 /]# mkdir -p /www/mongoDB/shard/s0
[root@100 /]# mkdir -p /www/mongoDB/shard/s1
[root@100 /]# mkdir -p /www/mongoDB/shard/s2
[root@100 /]# mkdir -p /www/mongoDB/shard/s3
[root@100 /]# mkdir -p /www/mongoDB/shard/log
[root@100 /]# /usr/local/mongoDB/bin/mongod --port 27020 --dbpath=/www/mongoDB/shard/s0 --logpath=/www/mongoDB/shard/log/s0.log --logappend --fork
....
[root@100 /]# /usr/local/mongoDB/bin/mongod --port 27023 --dbpath=/www/mongoDB/shard/s3 --logpath=/www/mongoDB/shard/log/s3.log --logappend --fork

步骤二: 启动Config Server

[root@100 /]# mkdir -p /www/mongoDB/shard/config
[root@100 /]# /usr/local/mongoDB/bin/mongod --port 27100 --dbpath=/www/mongoDB/shard/config --logpath=/www/mongoDB/shard/log/config.log --logappend --fork

注意:这里我们完全可以像启动普通mongodb服务一样启动,不需要添加—shardsvr和configsvr参数。因为这两个参数的作用就是改变启动端口的,所以我们自行指定了端口就可以。

步骤三: 启动Route Process

/usr/local/mongoDB/bin/mongos --port 40000 --configdb localhost:27100 --fork --logpath=/www/mongoDB/shard/log/route.log --chunkSize 500

mongos启动参数中,chunkSize这一项是用来指定chunk的大小的,单位是MB,默认大小为200MB.

步骤四: 配置Sharding

接下来,我们使用MongoDB Shell登录到mongos,添加Shard节点

[root@100 shard]# /usr/local/mongoDB/bin/mongo admin --port 40000
MongoDB shell version: 2.0.7
connecting to: 127.0.0.1:40000/admin
mongos> db.runCommand({ addshard:"localhost:27020" })
{ "shardAdded" : "shard0000", "ok" : 1 }
......
mongos> db.runCommand({ addshard:"localhost:27029" })
{ "shardAdded" : "shard0009", "ok" : 1 }
mongos> db.runCommand({ enablesharding:"test" }) #设置分片存储的数据库
{ "ok" : 1 }
mongos> db.runCommand({ shardcollection: "test.log", key: { id:1,time:1}})
{ "collectionsharded" : "test.log", "ok" : 1 }

步骤五: 程序代码内无需太大更改,直接按照连接普通的mongo数据库那样,将数据库连接接入接口40000

二十三、MongoDB 备份(mongodump)与恢复(mongorestore)

MongoDB数据备份

在Mongodb中我们使用mongodump命令来备份MongoDB数据。该命令可以导出所有数据到指定目录中。

mongodump命令可以通过参数指定导出的数据量级转存的服务器。

语法

mongodump命令脚本语法如下:

>mongodump -h dbhost -d dbname -o dbdirectory
  • -h:

    MongoDB 所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017

  • -d:

    需要备份的数据库实例,例如:test

  • -o:

    备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。

实例

在本地使用 27017 启动你的mongod服务。打开命令提示符窗口,进入MongoDB安装目录的bin目录输入命令mongodump:

>mongodump

执行以上命令后,客户端会连接到ip为 127.0.0.1 端口号为 27017 的MongoDB服务上,并备份所有数据到 bin/dump/ 目录中。命令输出结果如下:

MongoDB数据备份

mongodump 命令可选参数列表如下所示:

语法 描述 实例
mongodump --host HOST_NAME --port PORT_NUMBER 该命令将备份所有MongoDB数据 mongodump --host runoob.com --port 27017
mongodump --dbpath DB_PATH --out BACKUP_DIRECTORY mongodump --dbpath /data/db/ --out /data/backup/
mongodump --collection COLLECTION --db DB_NAME 该命令将备份指定数据库的集合。 mongodump --collection mycol --db test

MongoDB数据恢复

mongodb使用 mongorestore 命令来恢复备份的数据。

语法

mongorestore命令脚本语法如下:

>mongorestore -h <hostname><:port> -d dbname <path>
  • --host <:port>, -h <:port>:

    MongoDB所在服务器地址,默认为: localhost:27017

  • --db , -d :

    需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2

  • --drop:

    恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!

  • <path>:

    mongorestore 最后的一个参数,设置备份数据所在位置,例如:c:\data\dump\test。

    你不能同时指定 <path> 和 --dir 选项,--dir也可以设置备份目录。

  • --dir:

    指定备份的目录

    你不能同时指定 <path> 和 --dir 选项。

接下来我们执行以下命令:

>mongorestore

执行以上命令输出结果如下:

MongoDB数据恢复

二十四、MongoDB 监控

MongoDB中提供了mongostat 和 mongotop 两个命令来监控MongoDB的运行情况。


mongostat 命令

mongostat是mongodb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。

启动你的Mongod服务,进入到你安装的MongoDB目录下的bin目录, 然后输入mongostat命令,如下所示:

D:\set up\mongodb\bin>mongostat

以上命令输出结果如下:

mongotop 命令

mongotop也是mongodb下的一个内置工具,mongotop提供了一个方法,用来跟踪一个MongoDB的实例,查看哪些大量的时间花费在读取和写入数据。 mongotop提供每个集合的水平的统计数据。默认情况下,mongotop返回值的每一秒。

启动你的Mongod服务,进入到你安装的MongoDB目录下的bin目录, 然后输入mongotop命令,如下所示:

D:\set up\mongodb\bin>mongotop

以上命令执行输出结果如下:

带参数实例

 E:\mongodb-win32-x86_64-2.2.1\bin>mongotop 10

后面的10是<sleeptime>参数 ,可以不使用,等待的时间长度,以秒为单位,mongotop等待调用之间。通过的默认mongotop返回数据的每一秒。

 E:\mongodb-win32-x86_64-2.2.1\bin>mongotop --locks

报告每个数据库的锁的使用中,使用mongotop - 锁,这将产生以下输出:

输出结果字段说明:

  • ns:

    包含数据库命名空间,后者结合了数据库名称和集合。

  • db:

    包含数据库的名称。名为 . 的数据库针对全局锁定,而非特定数据库。

  • total:

    mongod花费的时间工作在这个命名空间提供总额。

  • read:

    提供了大量的时间,这mongod花费在执行读操作,在此命名空间。

  • write:

    提供这个命名空间进行写操作,这mongod花了大量的时间。

二十五、MongoDB Map Reduce

Map-Reduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。

MongoDB提供的Map-Reduce非常灵活,对于大规模数据分析也相当实用。

MapReduce 命令

以下是MapReduce的基本语法:

>db.collection.mapReduce(
   function() {emit(key,value);},  //map 函数
   function(key,values) {return reduceFunction},   //reduce 函数
   {
      out: collection,
      query: document,
      sort: document,
      limit: number
   }
)

使用 MapReduce 要实现两个函数 Map 函数和 Reduce 函数,Map 函数调用 emit(key, value), 遍历 collection 中所有的记录, 将 key 与 value 传递给 Reduce 函数进行处理。

Map 函数必须调用 emit(key, value) 返回键值对。

参数说明:

  • map :映射函数 (生成键值对序列,作为 reduce 函数参数)。
  • reduce 统计函数,reduce函数的任务就是将key-values变成key-value,也就是把values数组变成一个单一的值value。。
  • out 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)。
  • query 一个筛选条件,只有满足条件的文档才会调用map函数。(query。limit,sort可以随意组合)
  • sort 和limit结合的sort排序参数(也是在发往map函数前给文档排序),可以优化分组机制
  • limit 发往map函数的文档数量的上限(要是没有limit,单独使用sort的用处不大)

使用 MapReduce

考虑以下文档结构存储用户的文章,文档存储了用户的 user_name 和文章的 status 字段:

>db.posts.insert({
   "post_text": "bolong1",
   "user_name": "bolong1",
   "status":"active"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
   "post_text": "bolong1",
   "user_name": "bolong1",
   "status":"active"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
   "post_text": "bolong1",
   "user_name": "bolong1",
   "status":"active"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
   "post_text": "bolong1",
   "user_name": "bolong1",
   "status":"active"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
   "post_text": "bolong1",
   "user_name": "bolong1",
   "status":"disabled"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
   "post_text": "bolong2",
   "user_name": "bolong2",
   "status":"disabled"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
   "post_text": "bolong2",
   "user_name": "bolong2",
   "status":"disabled"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
   "post_text": "bolong2",
   "user_name": "bolong2",
   "status":"active"
})
WriteResult({ "nInserted" : 1 })

现在,我们将在 posts 集合中使用 mapReduce 函数来选取已发布的文章(status:"active"),并通过user_name分组,计算每个用户的文章数:

>db.posts.mapReduce( 
   function() { emit(this.user_name,1); }, 
   function(key, values) {return Array.sum(values)}, 
      {  
         query:{status:"active"},  
         out:"post_total" 
      }
)

以上 mapReduce 输出结果为:

{
        "result" : "post_total",
        "timeMillis" : 23,
        "counts" : {
                "input" : 5,
                "emit" : 5,
                "reduce" : 1,
                "output" : 2
        },
        "ok" : 1
}

结果表明,共有 5 个符合查询条件(status:"active")的文档, 在map函数中生成了 5 个键值对文档,最后使用reduce函数将相同的键值分为 2 组。

具体参数说明:

  • result:储存结果的collection的名字,这是个临时集合,MapReduce的连接关闭后自动就被删除了。
  • timeMillis:执行花费的时间,毫秒为单位
  • input:满足条件被发送到map函数的文档个数
  • emit:在map函数中emit被调用的次数,也就是所有集合中的数据总量
  • output:结果集合中的文档个数(count对调试非常有帮助)
  • ok:是否成功,成功为1
  • err:如果失败,这里可以有失败原因,不过从经验上来看,原因比较模糊,作用不大

使用 find 操作符来查看 mapReduce 的查询结果:

> var map=function() { emit(this.user_name,1); }
> var reduce=function(key, values) {return Array.sum(values)}
> var options={query:{status:"active"},out:"post_total"}
> db.posts.mapReduce(map,reduce,options)
{ "result" : "post_total", "ok" : 1 }
> db.post_total.find();

以上查询显示如下结果:

{ "_id" : "bolong1", "value" : 4 }
{ "_id" : "bolong2", "value" : 1 }

用类似的方式,MapReduce可以被用来构建大型复杂的聚合查询。

Map函数和Reduce函数可以使用 JavaScript 来实现,使得MapReduce的使用非常灵活和强大。

二十六、MongoDB GridFS

GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。

GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中。

GridFS 可以更好的存储大于16M的文件。

GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。

GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。

每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。

以下是简单的 fs.files 集合文档:

{
   "filename": "test.txt",
   "chunkSize": NumberInt(261120),
   "uploadDate": ISODate("2014-04-13T11:32:33.557Z"),
   "md5": "7b762939321e146569b07f72c62cca4f",
   "length": NumberInt(646)
}

以下是简单的 fs.chunks 集合文档:

{
   "files_id": ObjectId("534a75d19f54bfec8a2fe44b"),
   "n": NumberInt(0),
   "data": "Mongo Binary Data"
}

GridFS 添加文件

现在我们使用 GridFS 的 put 命令来存储 mp3 文件。 调用 MongoDB 安装目录下bin的 mongofiles.exe工具。

打开命令提示符,进入到MongoDB的安装目录的bin目录中,找到mongofiles.exe,并输入下面的代码:

>mongofiles.exe -d gridfs put song.mp3

-d gridfs 指定存储文件的数据库名称,如果不存在该数据库,MongoDB会自动创建。如果不存在该数据库,MongoDB会自动创建。Song.mp3 是音频文件名。

使用以下命令来查看数据库中文件的文档:

>db.fs.files.find()

以上命令执行后返回以下文档数据:

{
   _id: ObjectId('534a811bf8b4aa4d33fdf94d'), 
   filename: "song.mp3", 
   chunkSize: 261120, 
   uploadDate: new Date(1397391643474), md5: "e4f53379c909f7bed2e9d631e15c1c41",
   length: 10401959 
}

我们可以看到 fs.chunks 集合中所有的区块,以下我们得到了文件的 _id 值,我们可以根据这个 _id 获取区块(chunk)的数据:

>db.fs.chunks.find({files_id:ObjectId('534a811bf8b4aa4d33fdf94d')})

以上实例中,查询返回了 40 个文档的数据,意味着mp3文件被存储在40个区块中。


网站公告

今日签到

点亮在社区的每一天
去签到