数据库与持久化
你当前正在浏览历史版本 Vert.x 4.4.9 的文档。 访问本页面的 最新版本。

Vert.x Mongo 客户端

Vert.x 客户端允许应用程序与 MongoDB 实例进行交互,无论是保存、检索、搜索还是删除文档。 MongoDB 原生支持处理 JSON (BSON) 文档,因此它是 Vert.x 应用程序持久化数据的极佳搭档。

特性

  • 完全非阻塞

  • 自定义编解码器(Codec),支持 Vert.x JSON 与 BSON 之间的高性能序列化与反序列化

  • 支持 MongoDB Java 驱动绝大多数配置项

本客户端基于 MongoDB ReactiveStreams 驱动 构建。

使用 Vert.x Mongo 客户端

要在项目中使用该组件,请在构建描述文件的 dependencies 节点中添加以下依赖:

  • Maven(在 pom.xml 中):

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-mongo-client</artifactId>
  <version>5.0.12</version>
</dependency>
  • Gradle(在 build.gradle 文件中):

compile 'io.vertx:vertx-mongo-client:5.0.12'

创建客户端

你可以通过多种方式创建客户端:

使用默认共享池

在大多数情况下,你希望在不同的客户端实例之间共享同一个连接池。

例如,你可以通过部署多个 Verticle 实例来伸缩应用程序,并且希望每个 Verticle 实例共享同一个连接池,从而避免创建出多个连接池。

最简单的方式如下:

MongoClient client = MongoClient.createShared(vertx, config);

首次调用 MongoClient.createShared 时会真正创建连接池,并应用指定的配置。

后续调用将返回复用该连接池的新客户端实例,因此后续传入的配置将不会生效。

指定数据源连接池名称

你可以通过指定连接池名称来创建客户端,如下所示:

MongoClient client = MongoClient.createShared(vertx, config, "MyPoolName");

如果使用同一个 Vert.x 实例并在创建不同客户端时指定相同的连接池名称,它们将共享同一个连接池。

首次调用 MongoClient.createShared 时会真正创建连接池,并应用指定的配置。

后续调用将返回复用该连接池的新客户端实例,因此后续传入的配置将不会生效。

如果你希望不同组的客户端使用不同的连接池(例如它们需要与不同的数据库进行交互),可以使用这种方式进行创建。

创建非共享数据池的客户端

在大多数场景下,你需要在不同客户端实例之间共享连接池。 然而,有时你可能希望创建一个不与其他任何客户端共享连接池的客户端实例。

在这种情况下,你可以使用 MongoClient.create:

MongoClient client = MongoClient.create(vertx, config);

这等价于每次都使用唯一的连接池名称调用 MongoClient.createShared。

使用 API

客户端 API 由 MongoClient 表示。

保存文档

要保存文档,可以使用 save。

如果文档没有 \_id 字段,则执行插入(Insert)操作;否则,执行 更新或插入(Upsert) 操作。 Upsert 意味着如果文档尚不存在则插入,若已存在则更新。

如果插入的文档未指定 ID,则自动生成的 ID 字段将传递给结果处理器。

下面是保存文档并获取返回 ID 的示例:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit");
mongoClient.save("books", document).onComplete(res -> {
  if (res.succeeded()) {
    String id = res.result();
    System.out.println("Saved book with id " + id);
  } else {
    res.cause().printStackTrace();
  }
});

下面是保存已包含 ID 的文档的示例:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit")
  .put("_id", "123244");
mongoClient.save("books", document).onComplete(res -> {
  if (res.succeeded()) {
    // ...
  } else {
    res.cause().printStackTrace();
  }
});

插入文档

要插入文档,可以使用 insert。

如果插入的文档未包含 ID,则自动生成的 ID 字段将传递给结果处理器:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit");
mongoClient.insert("books", document).onComplete(res -> {
  if (res.succeeded()) {
    String id = res.result();
    System.out.println("Inserted book with id " + id);
  } else {
    res.cause().printStackTrace();
  }
});

如果插入文档时指定了 ID,且集合中已存在具有该 ID 的文档,则插入操作将失败:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit")
  .put("_id", "123244");
mongoClient.insert("books", document).onComplete(res -> {
  if (res.succeeded()) {
    // ...
  } else {
    // 若集合中已存在该 ID 的书籍,操作将失败
  }
});

更新文档

要更新文档,可以使用 updateCollection。

此操作会更新集合中的单个或多个文档。 传入 updateCollection 参数的 JSON 对象必须包含 更新操作符, 用于指定文档的更新规则。

通过 query 参数指定的 JSON 对象决定了集合中哪些文档将被更新。

下面是更新 books 集合中文档的示例:

JsonObject query = new JsonObject()
  .put("title", "The Hobbit");
// 设置 author 字段
JsonObject update = new JsonObject().put("$set", new JsonObject()
  .put("author", "J. R. R. Tolkien"));
mongoClient.updateCollection("books", query, update).onComplete(res -> {
  if (res.succeeded()) {
    System.out.println("Book updated !");
  } else {
    res.cause().printStackTrace();
  }
});

若需指定更新操作是否应执行 Upsert 或更新多个文档,可以使用 updateCollectionWithOptions 并传入 UpdateOptions 实例。

该配置类包含以下字段:

multi

设为 true 时更新所有匹配的多篇文档

upsert

设为 true 时,若 query 未匹配到任何文档则执行插入

writeConcern

本次操作的写入关注(Write Concern)级别

JsonObject query = new JsonObject()
  .put("title", "The Hobbit");
// 设置 author 字段
JsonObject update = new JsonObject().put("$set", new JsonObject()
  .put("author", "J. R. R. Tolkien"));
UpdateOptions options = new UpdateOptions().setMulti(true);
mongoClient.updateCollectionWithOptions("books", query, update, options).onComplete(res -> {
  if (res.succeeded()) {
    System.out.println("Book updated !");
  } else {
    res.cause().printStackTrace();
  }
});

替换文档

要替换文档,可以使用 replaceDocuments。

该操作与更新操作类似,但它不接受任何操作符,而是直接将整篇文档替换为你提供的新文档。

下面是替换 books 集合中文档的示例:

JsonObject query = new JsonObject()
  .put("title", "The Hobbit");
JsonObject replace = new JsonObject()
  .put("title", "The Lord of the Rings")
  .put("author", "J. R. R. Tolkien");
mongoClient.replaceDocuments("books", query, replace).onComplete(res -> {
  if (res.succeeded()) {
    System.out.println("Book replaced !");
  } else {
    res.cause().printStackTrace();
  }
});

批量操作

若要一次性执行多个插入、更新、替换或删除操作,可以使用 bulkWrite。

你可以传入一个 BulkOperation 列表,其中每个操作的行为与对应的单操作类似。 你可以根据需要传入任意数量的操作,甚至包含相同类型的多个操作。

若需指定批量操作是否按顺序(In Order)执行以及采用何种写入选项,可以使用 bulkWriteWithOptions,并传入 BulkWriteOptions 实例。 关于有序执行(Ordered)的更多说明,请参阅 操作执行文档。

查询文档

要查询文档,可以使用 find。

query 参数用于在集合中匹配文档。

下面是一个使用空查询条件匹配所有书籍的简单示例:

JsonObject query = new JsonObject();
mongoClient.find("books", query).onComplete(res -> {
  if (res.succeeded()) {
    for (JsonObject json : res.result()) {
      System.out.println(json.encodePrettily());
    }
  } else {
    res.cause().printStackTrace();
  }
});

下面是另一个匹配 Tolkien 所著全部书籍的示例:

JsonObject query = new JsonObject()
  .put("author", "J. R. R. Tolkien");
mongoClient.find("books", query).onComplete(res -> {
  if (res.succeeded()) {
    for (JsonObject json : res.result()) {
      System.out.println(json.encodePrettily());
    }
  } else {
    res.cause().printStackTrace();
  }
});

匹配到的文档将以 JSON 对象列表的形式返回给结果处理器。

若要指定返回字段、返回结果数量限制等,可以使用 findWithOptions 并传入 FindOptions 实例。

该配置类包含以下字段:

fields

结果中需要返回的字段。默认值为 null,表示返回所有字段

sort

用于排序的字段。默认值为 null

limit

返回结果数量的上限。默认值为 -1,表示返回所有结果

skip

返回结果前跳过的文档数量。默认值为 0

hint

强制使用的索引。默认值为空字符串

分批查询文档

当处理大数据集时,不建议直接使用 find 与 findWithOptions 方法。 为了避免将全部响应结果一次性加载到内存中导致内存膨胀,应使用 findBatch:

JsonObject query = new JsonObject()
  .put("author", "J. R. R. Tolkien");
mongoClient.findBatch("book", query)
  .exceptionHandler(throwable -> throwable.printStackTrace())
  .endHandler(v -> System.out.println("End of research"))
  .handler(doc -> System.out.println("Found doc: " + doc.encodePrettily()));

匹配到的文档将由 ReadStream 处理器逐一发射处理。

FindOptions 提供了额外的 batchSize 参数,可用于设置单次加载的文档数量:

JsonObject query = new JsonObject()
  .put("author", "J. R. R. Tolkien");
FindOptions options = new FindOptions().setBatchSize(100);
mongoClient.findBatchWithOptions("book", query, options)
  .exceptionHandler(throwable -> throwable.printStackTrace())
  .endHandler(v -> System.out.println("End of research"))
  .handler(doc -> System.out.println("Found doc: " + doc.encodePrettily()));

默认情况下,batchSize 设为 20。

查询单个文档

要查询单个文档,可以使用 findOne。

它的工作方式与 find 完全一致,但仅返回匹配的第一篇文档。

删除文档

要删除文档,可以使用 removeDocuments。

query 参数用于匹配集合中需要删除的文档。

下面是删除所有 Tolkien 书籍的示例:

JsonObject query = new JsonObject()
  .put("author", "J. R. R. Tolkien");
mongoClient.removeDocuments("books", query).onComplete(res -> {
  if (res.succeeded()) {
    System.out.println("Never much liked Tolkien stuff!");
  } else {
    res.cause().printStackTrace();
  }
});

删除单个文档

要删除单个文档,可以使用 removeDocument。

它的工作方式与 removeDocuments 类似,但仅删除匹配的第一篇文档。

统计文档数量

要统计文档数量,可以使用 count。

下面是统计 Tolkien 书籍总数的示例。文档数量将传递给结果处理器:

JsonObject query = new JsonObject()
  .put("author", "J. R. R. Tolkien");
mongoClient.count("books", query).onComplete(res -> {
  if (res.succeeded()) {
    long num = res.result();
  } else {
    res.cause().printStackTrace();
  }
});

管理 MongoDB 集合

所有 MongoDB 文档都存储在集合(Collection)中。

要获取所有集合的列表,可以使用 getCollections:

mongoClient.getCollections().onComplete(res -> {
  if (res.succeeded()) {
    List<String> collections = res.result();
  } else {
    res.cause().printStackTrace();
  }
});

要创建新集合,可以使用 createCollection:

mongoClient.createCollection("mynewcollectionr").onComplete(res -> {
  if (res.succeeded()) {
    // 创建成功!
  } else {
    res.cause().printStackTrace();
  }
});

要删除集合,可以使用 dropCollection:

删除集合将同时删除其中的所有文档!
mongoClient.dropCollection("mynewcollectionr").onComplete(res -> {
  if (res.succeeded()) {
    // 删除成功!
  } else {
    res.cause().printStackTrace();
  }
});

执行其他 MongoDB 命令

你可以使用 runCommand 执行任意原生 MongoDB 命令。

命令可用于运行更高级的 MongoDB 功能,例如 MapReduce。 有关更多信息,请查阅 MongoDB 文档中支持的 命令列表。

下面是一个执行聚合(Aggregate)命令的示例。注意,命令名称必须同时作为参数传入,并包含在表示该命令的 JSON 对象中。这是因为 JSON 是无序的,而 BSON 是有序的,MongoDB 要求 BSON 的第一个条目必须是命令名称。为了让客户端明确 JSON 中哪个条目是命令名称,必须显式将其作为参数指定:

JsonObject command = new JsonObject()
  .put("aggregate", "collection_name")
  .put("pipeline", new JsonArray());
mongoClient.runCommand("aggregate", command).onComplete(res -> {
  if (res.succeeded()) {
    JsonArray resArr = res.result().getJsonArray("result");
    // 等后续处理
  } else {
    res.cause().printStackTrace();
  }
});

MongoDB Extended JSON 支持

目前仅支持 date、oid 和 binary 类型 (请参阅 MongoDB Extended JSON)。

下面是插入包含 date 字段文档的示例:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit")
  // ISO-8601 日期
  .put("publicationDate", new JsonObject().put("$date", "1937-09-21T00:00:00+00:00"));
mongoService.save("publishedBooks", document).compose(id -> {
  return mongoService.findOne("publishedBooks", new JsonObject().put("_id", id), null);
}).onComplete(res -> {
  if (res.succeeded()) {
    System.out.println("To retrieve ISO-8601 date : "
      + res.result().getJsonObject("publicationDate").getString("$date"));
  } else {
    res.cause().printStackTrace();
  }
});

下面是在 Java 中插入包含二进制(Binary)字段的文档并将其读取回来的示例:

byte[] binaryObject = new byte[40];
JsonObject document = new JsonObject()
  .put("name", "Alan Turing")
  .put("binaryStuff", new JsonObject().put("$binary", binaryObject));
mongoService.save("smartPeople", document).compose(id -> {
  return mongoService.findOne("smartPeople", new JsonObject().put("_id", id), null);
}).onComplete(res -> {
  if (res.succeeded()) {
    byte[] reconstitutedBinaryObject = res.result().getJsonObject("binaryStuff").getBinary("$binary");
    // 实际业务中此时可将其反序列化为具体对象
  } else {
    res.cause().printStackTrace();
  }
});

下面是插入 Base64 编码字符串、将其类型标记为二进制字段并读取回来的示例:

String base64EncodedString = "a2FpbHVhIGlzIHRoZSAjMSBiZWFjaCBpbiB0aGUgd29ybGQ=";
JsonObject document = new JsonObject()
  .put("name", "Alan Turing")
  .put("binaryStuff", new JsonObject().put("$binary", base64EncodedString));
mongoService.save("smartPeople", document).compose(id -> {
  return mongoService.findOne("smartPeople", new JsonObject().put("_id", id), null);
}).onComplete(res -> {
  if (res.succeeded()) {
    String reconstitutedBase64EncodedString = res.result().getJsonObject("binaryStuff").getString("$binary");
    // 此时可将该 Base64 字符串重新转换回原始字节数组
  } else {
    res.cause().printStackTrace();
  }
});

下面是插入 ObjectID 并读取回来的示例:

String individualId = new ObjectId().toHexString();
JsonObject document = new JsonObject()
  .put("name", "Stephen Hawking")
  .put("individualId", new JsonObject().put("$oid", individualId));
mongoService.save("smartPeople", document).compose(id -> {
  JsonObject query = new JsonObject().put("_id", id);
  return mongoService.findOne("smartPeople", query, null);
}).onComplete(res -> {
  if (res.succeeded()) {
    String reconstitutedIndividualId = res.result().getJsonObject("individualId").getString("$oid");
  } else {
    res.cause().printStackTrace();
  }
});

获取去重字段值(Distinct)

下面是获取去重字段值的示例:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit");
mongoClient.save("books", document).compose(v -> {
  return mongoClient.distinct("books", "title", String.class.getName());
}).onComplete(res -> {
  if (res.succeeded()) {
    System.out.println("Title is : " + res.result().getJsonArray(0));
  } else {
    res.cause().printStackTrace();
  }
});

下面是批处理模式下获取去重字段值的示例:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit");
mongoClient.save("books", document).onComplete(res -> {
  if (res.succeeded()) {
    mongoClient.distinctBatch("books", "title", String.class.getName())
      .handler(book -> System.out.println("Title is : " + book.getString("title")));
  } else {
    res.cause().printStackTrace();
  }
});
  • 下面是结合查询条件获取去重字段值的示例:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit")
  .put("publicationDate", new JsonObject().put("$date", "1937-09-21T00:00:00+00:00"));
JsonObject query = new JsonObject()
  .put("publicationDate",
    new JsonObject().put("$gte", new JsonObject().put("$date", "1937-09-21T00:00:00+00:00")));
mongoClient.save("books", document).compose(v -> {
  return mongoClient.distinctWithQuery("books", "title", String.class.getName(), query);
}).onComplete(res -> {
  if (res.succeeded()) {
    System.out.println("Title is : " + res.result().getJsonArray(0));
  }
});

下面是在批处理模式下结合查询条件获取去重字段值的示例:

JsonObject document = new JsonObject()
  .put("title", "The Hobbit")
  .put("publicationDate", new JsonObject().put("$date", "1937-09-21T00:00:00+00:00"));
JsonObject query = new JsonObject()
  .put("publicationDate", new JsonObject()
    .put("$gte", new JsonObject().put("$date", "1937-09-21T00:00:00+00:00")));
mongoClient.save("books", document).onComplete(res -> {
  if (res.succeeded()) {
    mongoClient.distinctBatchWithQuery("books", "title", String.class.getName(), query)
      .handler(book -> System.out.println("Title is : " + book.getString("title")));
  }
});

存储与检索文件及二进制数据

客户端可以使用 MongoDB GridFS 存储与检索文件及二进制数据。 你可以使用 MongoGridFsClient 向 GridFS 上传或从 GridFS 下载文件与数据流。

获取 MongoGridFsClient 与 GridFS 交互

调用 createGridFsBucketService 并提供 Bucket 名称即可创建 MongoGridFsClient。在 GridFS 中,Bucket 名称最终对应一个包含所有已存储对象引用的集合。 你可以通过指定唯一的 Bucket 名称将对象隔离到不同的 Bucket 中。

参数说明:

bucketName : 待创建的 Bucket 名称

下面是获取自定义 Bucket 名称的 MongoGridFsClient 的示例:

mongoClient.createGridFsBucketService("bakeke").onComplete(res -> {
  if (res.succeeded()) {
    // 与 GridFS 客户端进行交互...
    MongoGridFsClient client = res.result();
  } else {
    res.cause().printStackTrace();
  }
});

GridFS 默认使用名为 "fs" 的 Bucket。如果你希望直接获取默认 Bucket 而无需自定义名称,可以调用 createDefaultGridFsBucketService。

下面是获取默认 Bucket 名称的 MongoGridFsClient 的示例:

mongoClient.createDefaultGridFsBucketService().onComplete(res -> {
  if (res.succeeded()) {
    // 与 GridFS 客户端进行交互...
    MongoGridFsClient client = res.result();
  } else {
    res.cause().printStackTrace();
  }
});

从 GridFS 中删除整个文件 Bucket

可以使用 drop 删除整个文件 Bucket 及其包含的所有内容。它将删除创建 MongoGridFsClient 时指定的 Bucket。

下面是删除文件 Bucket 的示例:

gridFsClient.drop().onComplete(res -> {
  if (res.succeeded()) {
    // 文件 Bucket 已被删除,其中的所有文件均被抹除
  } else {
    res.cause().printStackTrace();
  }
});

查询 GridFS Bucket 中的所有文件 ID

可以使用 findAllIds 获取 Bucket 中所有文件的 ID 列表。 随后可以通过 downloadFileByID 根据 ID 下载文件。

下面是检索文件 ID 列表的示例:

gridFsClient.findAllIds().onComplete(res -> {
  if (res.succeeded()) {
    List<String> ids = res.result(); // 文件 ID 列表
  } else {
    res.cause().printStackTrace();
  }
});

根据查询条件检索 GridFS Bucket 中的文件 ID

可以指定查询条件来匹配 GridFS Bucket 中的文件。findIds 将返回匹配该查询条件的文件 ID 列表。

参数说明:

query : 这是一个可以使用标准 MongoDB 查询操作符匹配文件元数据的 JSON 对象。空 JSON 对象将匹配所有文档。你可以按照 GridFS 手册中的说明查询 GridFS 文件集合的属性:https://docs.mongodb.com/manual/core/gridfs/#the-files-collection

获取 ID 后,可以使用 downloadFileByID 根据文件 ID 进行下载。

下面是基于元数据查询检索文件 ID 列表的示例:

JsonObject query = new JsonObject().put("metadata.nick_name", "Puhi the eel");
gridFsClient.findIds(query).onComplete(res -> {
  if (res.succeeded()) {
    List<String> ids = res.result(); // 文件 ID 列表
  } else {
    res.cause().printStackTrace();
  }
});

根据 ID 删除 GridFS 中的文件

可以通过传入文件 ID 调用 delete 删除先前存储在 GridFS 中的文件。文件 ID 可以使用 findIds 通过查询获取。

参数说明: id : 存储文件时由 GridFS 生成的文件 ID

下面是根据 ID 删除文件的示例:

String id = "56660b074cedfd000570839c"; // 文件的 GridFS ID
gridFsClient.delete(id).onComplete(res -> {
  if (res.succeeded()) {
    // 文件已删除
  } else {
    // 发生异常
    res.cause().printStackTrace();
  }
});

上传文件到 GridFS

可以通过文件名使用 uploadFile 存储文件。上传成功后将返回 GridFS 生成的文件 ID,该 ID 可用于后续检索文件。

参数说明:

fileName : 保存到 GridFS 中所使用的文件名

gridFsClient.uploadFile("file.name").onSuccess(id -> {
  // 存储在 GridFS 中的对象 ID
});

带配置选项上传文件到 GridFS

可以使用 uploadFileWithOptions 并传入 GridFsUploadOptions 实例以携带附加选项存储文件。上传成功后将返回 GridFS 生成的文件 ID。

字段说明:

metadata : 包含后续检索时可能用到的任何元数据的 JSON 对象 chunkSizeBytes : GridFS 将文件分块存储的分块大小(字节)

下面是指定分块大小与元数据上传文件的示例:

JsonObject metadata = new JsonObject();
metadata.put("nick_name", "Puhi the Eel");

GridFsUploadOptions options = new GridFsUploadOptions();
options.setChunkSizeBytes(1024);
options.setMetadata(metadata);

gridFsClient.uploadFileWithOptions("file.name", options).onSuccess(id -> {
  // 存储在 GridFS 中的对象 ID
});

下载 GridFS 中已存储的文件

可以使用 downloadFile 通过文件的原始名称进行下载。 下载完成后,结果处理器将以 Long 形式返回下载文件的长度。

字段说明:

fileName

先前存储的文件名

下面是使用存储在 GridFS 中的文件名下载文件的示例:

gridFsClient.downloadFile("file.name").onSuccess(fileLength -> {
});

根据文件 ID 下载 GridFS 中的文件

可以使用 downloadFileByID 根据文件 ID 将文件下载到指定的文件名中。 下载成功后,结果处理器将以 Long 形式返回下载文件的长度。

字段说明:

id : 存储文件时由 GridFS 生成的文件 ID

下面是使用存储到 GridFS 时分配的 ID 下载文件的示例:

String id = "56660b074cedfd000570839c";
String filename = "puhi.fil";
gridFsClient.downloadFileByID(id, filename).onSuccess(fileLength -> {
  // 存储到 fileName 的文件长度
});

将 GridFS 中的文件重命名下载

可以使用 downloadFileAs 根据原始文件名解析文件,并将其下载为新的文件名。 下载成功后,结果处理器将以 Long 形式返回下载文件的长度。

字段说明:

fileName : 先前存储的文件名 newFileName : 文件下载保存时使用的新文件名

gridFsClient.downloadFileAs("file.name", "new_file.name").onComplete(fileLength -> {
  // 存储到 fileName 的文件长度
});

上传数据流至 GridFS

可以使用 uploadByFileName 将数据流上传到 GridFS。 数据流上传完毕后,结果处理器将接收到 GridFS 生成的文件 ID。

字段说明:

stream : 待上传的 ReadStream fileName : 数据流在 GridFS 中存储的文件名

下面是将文件流上传到 GridFS 的示例:

gridFsStreamClient.uploadByFileName(asyncFile, "kanaloa").onSuccess(id -> {
});

带配置选项上传数据流至 GridFS

可以使用 uploadByFileNameWithOptions 并传入 GridFsUploadOptions 实例将数据流上传到 GridFS。 数据流上传完毕后,结果处理器将接收到 GridFS 生成的文件 ID。

字段说明:

stream : 待上传的 ReadStream fileName : 数据流在 GridFS 中存储的文件名 options : 上传配置选项

GridFsUploadOptions 包含以下字段:

metadata : 包含后续检索时可能用到的任何元数据的 JSON 对象 chunkSizeBytes : GridFS 将文件分块存储的分块大小(字节)

下面是带配置选项将文件流上传到 GridFS 的示例:

GridFsUploadOptions options = new GridFsUploadOptions();
options.setChunkSizeBytes(2048);
options.setMetadata(new JsonObject().put("catagory", "Polynesian gods"));
gridFsStreamClient.uploadByFileNameWithOptions(asyncFile, "kanaloa", options).onSuccess(id -> {
});

根据文件名将文件从 GridFS 下载为数据流

可以使用 downloadByFileName 根据文件名从 GridFS 下载数据流。 数据流下载完毕后,结果处理器将接收到以 Long 形式表示的数据流长度。

字段说明:

stream : 用于接收下载数据的 WriteStream fileName : 将下载到流中的文件名

下面是将文件下载为数据流的示例:

gridFsStreamClient.downloadByFileName(asyncFile, "kamapuaa.fil").onSuccess(length -> {
});

带配置选项根据文件名将文件从 GridFS 下载为数据流

可以使用 downloadByFileNameWithOptions 并传入 GridFsDownloadOptions 实例,通过文件名及下载选项从 GridFS 下载数据流。 数据流下载完毕后,结果处理器将接收到以 Long 形式表示的数据流长度。

字段说明:

stream : 用于接收下载数据的 WriteStream fileName : 将下载到流中的文件名 options : GridFsDownloadOptions 实例

DownloadOptions 包含以下字段:

revision : 待下载文件的修订版本(Revision)

下面是带选项将文件下载为数据流的示例:

GridFsDownloadOptions options = new GridFsDownloadOptions();
options.setRevision(0);
gridFsStreamClient.downloadByFileNameWithOptions(asyncFile, "kamapuaa.fil", options).onSuccess(length -> {
});

根据 ID 将文件从 GridFS 下载为数据流

可以使用 downloadById 通过 GridFS 生成的 ID 下载数据流。 数据流下载完毕后,结果处理器将接收到以 Long 形式表示的数据流长度。

字段说明:

stream : 用于接收下载数据的 WriteStream id : GridFS 生成的文件 ID 的字符串表示

下面是使用对象 ID 将文件下载为数据流的示例:

String id = "58f61bf84cedfd000661af06";
gridFsStreamClient.downloadById(asyncFile, id).onSuccess(length -> {
});

配置客户端

客户端通过 JSON 对象进行配置。

Mongo 客户端支持以下基础配置项:

db_name

所使用的 MongoDB 实例中的数据库名称。默认值为 default_db

useObjectId

该开关项用于控制是否将 ObjectId 作为字符串进行持久化与检索。若设为 true,十六进制字符串将作为原生 MongoDB ObjectId 类型保存在文档集合中。这使得你可以基于创建时间对文档进行排序。你还可以通过十六进制字符串使用 ObjectId::getDate() 提取创建时间。若需选用其他类型,请设为 false。若设为 false 或保留默认值,且文档中省略了 _id 字段,则会生成十六进制字符串作为文档的 _id。默认值为 false。

Mongo 客户端尽量支持官方驱动允许的大多数选项。有两种配置驱动所用 MongoDB 连接的方式:通过连接字符串,或者通过单独的配置选项。

connection_string

驱动用于创建客户端的连接字符串。例如 mongodb://localhost:27017。关于连接字符串格式的更多信息,请查阅驱动官方文档。

驱动专用配置选项

{
  // 单节点/集群通用基础配置
  "host" : "127.0.0.1", // 字符串
  "port" : 27017,      // 整数

  // 副本集/集群多节点配置
  "hosts" : [
    {
      "host" : "cluster1", // 字符串
      "port" : 27000       // 整数
    },
    {
      "host" : "cluster2", // 字符串
      "port" : 28000       // 整数
    },
    ...
  ],
  "replicaSet" :  "foo",    // 字符串
  "serverSelectionTimeoutMS" : 30000, // 长整数

  // 连接池配置
  "maxPoolSize" : 50,                // 整数
  "minPoolSize" : 25,                // 整数
  "maxIdleTimeMS" : 300000,          // 长整数
  "maxLifeTimeMS" : 3600000,         // 长整数
  "waitQueueTimeoutMS" : 10000,      // 长整数
  "maintenanceFrequencyMS" : 2000,   // 长整数
  "maintenanceInitialDelayMS" : 500, // 长整数

  // 认证与凭据
  "username"   : "john",     // 字符串
  "password"   : "secret",   // 字符串
  "authSource" : "some.db"   // 字符串
  // 认证机制
  "authMechanism"     : "GSSAPI",        // 字符串
  "gssapiServiceName" : "myservicename", // 字符串

  // 套接字配置
  "connectTimeoutMS" : 300000, // 整数
  "socketTimeoutMS"  : 100000, // 整数
  "sendBufferSize"    : 8192,  // 整数
  "receiveBufferSize" : 8192,  // 整数

  // 服务端设置
  "heartbeatFrequencyMS"    : 1000, // 长整数
  "minHeartbeatFrequencyMS" :  500, // 长整数

  // SSL 配置
  "ssl" : false,                       // 布尔值
  "sslInvalidHostNameAllowed" : false, // 布尔值
  "trustAll" : false,                  // 布尔值
  "keyPath" : "key.pem",               // 字符串
  "certPath" : "cert.pem",             // 字符串
  "caPath" : "ca.pem",                 // 字符串

  // 网络传输压缩配置
  "compressors"           : ["zstd", "snappy", "zlib"],  // 字符串数组
  "zlibCompressionLevel"  : 6                            // 整数
}

驱动选项详细说明

host

MongoDB 实例运行的主机名/IP。默认值为 127.0.0.1。若指定了 hosts 则忽略此项

port

MongoDB 实例监听的端口。默认值为 27017。若指定了 hosts 则忽略此项

hosts

支持 MongoDB 集群(分片集群/副本集)的主机和端口数组

host

集群中的主机

port

集群中主机监听的端口

replicaSet

若 MongoDB 实例是副本集成员,则为 Replica Set 的名称

serverSelectionTimeoutMS

在抛出错误前,Mongo 驱动为某项操作选择可用服务器的最大等待时间(毫秒)

maxPoolSize

连接池中的最大连接数。默认值为 100

minPoolSize

连接池中的最小连接数。默认值为 0

maxIdleTimeMS

池化连接的最大空闲时间(毫秒)。默认值为 0,表示无限制

maxLifeTimeMS

池化连接的最长生存时间(毫秒)。默认值为 0,表示无限制

waitQueueTimeoutMS

线程等待连接变为可用状态的最大等待时间(毫秒)。默认值为 120000(2 分钟)

maintenanceFrequencyMS

连接池维护作业的运行间隔周期(毫秒)。默认值为 0

maintenanceInitialDelayMS

在连接池上运行首次维护作业前的初始延迟等待时间(毫秒)。默认值为 0

username

用于认证的用户名。默认值为 null(表示无需认证)

password

用于认证的密码

authSource

与用户凭据关联的数据库名称。默认值为 db_name 的值

authMechanism

所使用的认证机制。详情请参阅 Authentication

gssapiServiceName

当 authMechanism 指定为 GSSAPI 时的 Kerberos 服务名称

connectTimeoutMS

连接建立超时时间(毫秒)。默认值为 10000(10 秒)

socketTimeoutMS

套接字发送或接收操作的超时时间(毫秒)。默认值为 0,表示无超时

sendBufferSize

设置套接字的发送缓冲区大小(SO_SNDBUF)。默认值为 0,表示使用操作系统默认设置

receiveBufferSize

设置套接字的接收缓冲区大小(SO_RCVBUF)。默认值为 0,表示使用操作系统默认设置

heartbeatFrequencyMS

集群监控器尝试与各服务器通信的心跳频率(毫秒)。默认值为 5000(5 秒)

minHeartbeatFrequencyMS

最小心跳频率(毫秒)。默认值为 1000(1 秒)

ssl

是否在 vertx-mongo-client 与 MongoDB 之间启用 SSL

sslInvalidHostNameAllowed

是否接受未包含在服务器证书中的主机名

trustAll

使用 SSL 时,是否信任 所有 证书。警告 - 信任所有证书会使你面临中间人攻击(MITM)等潜在安全隐患

keyPath

客户端密钥文件的路径,用于在与 MongoDB 建立 SSL 连接时向服务端进行身份认证

certPath

客户端证书文件的路径,用于在与 MongoDB 建立 SSL 连接时向服务端进行身份认证

caPath

CA 证书文件的路径,在与 MongoDB 建立 SSL 连接时作为信任源

compressors

设置网络传输的压缩算法。可选有效值为 [snappy, zlib, zstd],默认值为 null(表示不压缩)

若需支持 snappy 与 zstd 压缩算法,必须在项目构建描述文件中添加额外的依赖库(分别对应 snappy-java 与 zstd-java)。

zlibCompressionLevel

设置 zlib 的压缩级别。有效取值范围为 -1 到 9 之间,启用 zlib 时默认值为 -1。

上述列出的大多数默认值均直接继承自 MongoDB Java 驱动的默认配置。