文档 (Document)
Overview
在本指南中,您可以了解如何使用 MongoDB Java 驱动程序中的文档。
MongoDB 文档是种数据结构,包含二进制 JSON (BSON) 形式的键/值字段。您可以使用文档及其字段中包含的数据来存储数据,也可以在 MongoDB 中发布命令或查询。
有关文档的术语、结构和限制的更多信息,请参阅 MongoDB 手册中的文档页面。
MongoDB Java 驱动程序和 BSON 库包含以下类,可帮助您访问和操作文档中的 BSON 数据:
名称 | 安装包 | 实施地图 | 推荐用法 |
---|---|---|---|
Document | org.bson | 是,实现 Map<String, Object> | 当您需要灵活简洁的数据表示时。 |
BsonDocument | org.bson | 是,实现 Map<String, BsonValue> | 当您需要类型安全的 API 时。 |
JsonObject | org.bson.json | No | 当您只想处理 JSON 字符串时。 |
BasicDBObject | com.mongodb | No | 通过旧版驱动程序版本迁移应用程序时。 |
虽然您可以在应用程序中使用其中任何类,但我们建议您使用 Document
类,因为其可以简明地表示任何复杂程度的动态结构文档。其实现了 Map<String, Object>
接口,从而可以使用松散类型值。
文档
Document
类可灵活地表示 BSON 文档。通过该类,您可以使用标准库中的 Java 类型访问和操作字段。有关常用 BSON 和 Java 类型之间的映射关系,请参阅下表:
BSON 类型 | Java 类型 |
---|---|
阵列 | java.util.List |
二进制文件 | org.bson.types.Binary |
布尔 | java.lang.Boolean |
Date | java.util.Date |
文档 | org.bson.Document |
double | java.lang.Double |
Int32 | java.lang.Integer |
Int64 | java.lang.Long |
null | null |
ObjectId | org.bson.types.ObjectId |
字符串 | java.lang.String |
前面的映射表显示了使用Document
类时的默认映射。 您可以通过指定自定义编解码器来自定义类型映射。 有关自定义映射类型的更多信息,请参阅我们的编解码器使用指南。
以下代码片段中,我们将展示如何实例化和构建示例 Document
实例,该实例代表包含多种不同字段类型的文档:
Document author = new Document("_id", new ObjectId()) .append("name", "Gabriel García Márquez") .append("dateOfDeath", Date.from(LocalDate.of(2014, 4, 17).atStartOfDay(ZoneId.systemDefault()).toInstant())) .append("novels", Arrays.asList( new Document("title", "One Hundred Years of Solitude").append("yearPublished", 1967), new Document("title", "Chronicle of a Death Foretold").append("yearPublished", 1981), new Document("title", "Love in the Time of Cholera").append("yearPublished", 1985)));
要将该文档插入到某一集合中,请使用 getCollection()
方法实例化一个集合,然后调用 insertOne 操作,具体操作如下:
// MongoClient mongoClient = <code to instantiate your client>; MongoDatabase database = mongoClient.getDatabase("fundamentals_data"); MongoCollection<Document> collection = database.getCollection("authors"); InsertOneResult result = collection.insertOne(author);
成功执行插入操作后,可以使用以下代码从集合中检索示例文档数据:
import com.mongodb.client.model.Filters; // <MongoCollection setup code here> Document doc = collection.find(Filters.eq("name", "Gabriel García Márquez")).first(); if (doc != null) { System.out.println("_id: " + doc.getObjectId("_id") + ", name: " + doc.getString("name") + ", dateOfDeath: " + doc.getDate("dateOfDeath")); doc.getList("novels", Document.class).forEach((novel) -> { System.out.println("title: " + novel.getString("title") + ", yearPublished: " + novel.getInteger("yearPublished")); }); }
提示
前面的代码样本使用辅助方法检查返回类型,并在无法转换字段值时引发异常。您可以调用 Map
接口指定的 get()
方法来检索类型为 Object
的字段值并跳过类型检查。
输出结果应如下所示:
_id: 5fb5fad05f734e3794741a35, name: Gabriel García Márquez, dateOfDeath: Thu Apr 17 00:00:00 EDT 2014 title: One Hundred Years of Solitude, yearPublished: 1967 title: Chronicle of a Death Foretold, yearPublished: 1981 title: Love in the Time of Cholera, yearPublished: 1985
有关检索和操作 MongoDB 数据的更多信息,请参阅我们的增删改查指南。
有关本节中提到的方法和类的详情,请参阅以下 API 文档:
BsonDocument
BsonDocument
类提供了类型安全的 API 来访问和操作 BSON 文档。您需要为每个字段指定 Java BSON 库中的 BSON 类型。常用的 BSON 和 Java BSON 库类型之间的映射关系如下表所示:
BSON 类型 | Java BSON 库类型 |
---|---|
阵列 | org.bson.BsonArray |
二进制文件 | org.bson.BsonBinary |
布尔 | org.bson.Boolean |
日期(长值) | org.bson.BsonDateTime |
文档 | org.bson.BsonDocument |
double | org.bson.BsonDouble |
Int32 | org.bson.BsonInt32 |
Int64 | org.bson.BsonInt64 |
null | org.bson.BsonNull |
ObjectId | org.bson.BsonObjectId |
字符串 | org.bson.BsonString |
以下代码片段中,我们将展示如何实例化和构建示例 BsonDocument
实例,该实例代表包含多种不同字段类型的文档:
BsonDocument author = new BsonDocument() .append("_id", new BsonObjectId()) .append("name", new BsonString("Gabriel García Márquez")) .append("dateOfDeath", new BsonDateTime(LocalDate.of(2014, 4, 17).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli())) .append("novels", new BsonArray(Arrays.asList( new BsonDocument().append("title", new BsonString("One Hundred Years of Solitude")).append("yearPublished", new BsonInt32(1967)), new BsonDocument().append("title", new BsonString("Chronicle of a Death Foretold")).append("yearPublished", new BsonInt32(1981)), new BsonDocument().append("title", new BsonString("Love in the Time of Cholera")).append("yearPublished", new BsonInt32(1985)) )));
要将此文档插入到某一集合中,请使用 getCollection()
方法实例化一个集合,而此方法会将 BsonDocument
类指定为 documentClass
参数。然后,按以下方法调用 insertOne 操作:
// MongoClient mongoClient = <code to instantiate your client>; MongoDatabase database = mongoClient.getDatabase("fundamentals_data"); MongoCollection<BsonDocument> collection = database.getCollection("authors", BsonDocument.class); InsertOneResult result = collection.insertOne(author);
成功执行插入操作后,可以使用以下代码从集合中检索示例文档数据:
import com.mongodb.client.model.Filters; // <MongoCollection setup code here> BsonDocument doc = collection.find(Filters.eq("name", "Gabriel García Márquez")).first(); if (doc != null) { System.out.println("_id: " + doc.getObjectId("_id").getValue() + ", name: " + doc.getString("name").getValue() + ", dateOfDeath: " + new Date(doc.getDateTime("dateOfDeath").getValue())); doc.getArray("novels").forEach((novel) -> { System.out.println("title: " + novel.asDocument().getString("title").getValue() + ", yearPublished: " + novel.asDocument().getInt32("yearPublished").getValue()); }); }
提示
前面的代码样本使用辅助方法检查返回类型,并在无法转换字段值时引发 BsonInvalidOperationException
。您可以调用 Map
接口指定的 get()
方法来检索类型为 BsonValue
的字段值并跳过类型检查。
输出结果应如下所示:
_id: 5fb5fad05f734e3794741a35, name: Gabriel García Márquez, dateOfDeath: Thu Apr 17 00:00:00 EDT 2014 title: One Hundred Years of Solitude, yearPublished: 1967 title: Chronicle of a Death Foretold, yearPublished: 1981 title: Love in the Time of Cholera, yearPublished: 1985
有关本节中提到的方法和类的详情,请参阅以下 API 文档:
JsonObject
JsonObject
类作为 JSON 字符串的包装器。如果只想处理 JSON 数据,可以使用 JsonObject
来避免将数据不必要地转换为 Map
对象。
默认情况下, JsonObject
存储扩展 JSON 。 您可以在JsonObject
中自定义 JSON 格式,具体方法是指定JsonObjectCodec
并向其传递JsonWriterSettings
对象。 有关 JSON 格式的更多信息,请参阅我们的扩展 JSON 指南。 有关指定编解码器的更多信息,请参阅我们的编解码器指南。
在以下代码片段中,我们展示了如何实例化示例 JsonObject
实例,该实例包装包含不同类型键值对的扩展 JSON 字符串:
String ejsonStr = "{\"_id\": {\"$oid\": \"6035210f35bd203721c3eab8\"}," + "\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"," + "\"dateOfDeath\": {\"$date\": \"2014-04-17T04:00:00Z\"}," + "\"novels\": [" + "{\"title\": \"One Hundred Years of Solitude\",\"yearPublished\": 1967}," + "{\"title\": \"Chronicle of a Death Foretold\",\"yearPublished\": 1981}," + "{\"title\": \"Love in the Time of Cholera\",\"yearPublished\": 1985}]}"; JsonObject author = new JsonObject(ejsonStr);
要将此文档插入到某一集合中,请使用 getCollection()
方法实例化一个集合,而此方法会将 JsonObject
类指定为 documentClass
参数。然后,按以下方法调用 insertOne 操作:
// MongoClient mongoClient = <code to instantiate your client>; MongoDatabase database = mongoClient.getDatabase("fundamentals_data"); MongoCollection<JsonObject> collection = database.getCollection("authors", JsonObject.class); InsertOneResult result = collection.insertOne(author);
成功执行插入操作后,可以从集合中检索 JSON 示例数据。您可以使用任何扩展了 Bson
的类来指定查询,下面介绍了如何使用 JsonObject
查询数据:
// MongoClient mongoClient = <code to instantiate your client>; JsonObject query = new JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}"); JsonObject jsonResult = collection.find(query).first(); if (jsonResult != null) { System.out.println("query result in extended json format: " + jsonResult.getJson()); }
输出结果应如下所示:
query result in extended json format: {"_id": {"$oid": "6035210f35bd203721c3eab8"}, "name": "Gabriel García Márquez", "dateOfDeath": {"$date": "2014-04-17T04:00:00Z"}, "novels": [{"title": "One Hundred Years of Solitude", "yearPublished": 1967}, {"title": "Chronicle of a Death Foretold", "yearPublished": 1981}, {"title": "Love in the Time of Cholera", "yearPublished": 1985}]}
提示
如果想在应用程序中使用其他格式的 JSON 字符串,则您可以使用 JsonObjectCodec
类和 JsonWriterSettings
来指定所需的 JSON 格式。
以下代码示例使用宽松模式 JSON字符串读取和写入 MongoDB 实例,并将ObjectId
实例输出为十六进制字符串:
import static org.bson.codecs.configuration.CodecRegistries.fromCodecs; // MongoClient mongoClient = <code to instantiate your client>; MongoDatabase database = mongoClient.getDatabase("fundamentals_data"); MongoCollection<JsonObject> collection = database.getCollection("authors", JsonObject.class) .withCodecRegistry( fromCodecs( // define a JsonObjectCodec with a JsonWriterSettings in Relaxed mode new JsonObjectCodec(JsonWriterSettings .builder() .outputMode(JsonMode.RELAXED) .objectIdConverter((objectId, strictJsonWriter) -> { strictJsonWriter.writeString(objectId.toHexString()); }) .build()))); JsonObject author = new JsonObject("{\"_id\": \"6035210f35bd203721c3eab8\", " + "\"name\": \"Gabriel García Márquez\", " + "\"dateOfDeath\": {\"$date\": \"2014-04-17T04:00:00Z\"}, " + "\"novels\": [{\"title\": \"One Hundred Years of Solitude\", \"yearPublished\": 1967}, {\"title\": \"Chronicle of a Death Foretold\", \"yearPublished\": 1981}, " + "{\"title\": \"Love in the Time of Cholera\", \"yearPublished\": 1985}]}\n"); collection.insertOne(author); JsonObject query = new JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}"); JsonObject jsonResult = collection.find(query).first(); if (jsonResult != null) { System.out.println("query result in relaxed json format: " + jsonResult.getJson()); }
此代码的输出应如下所示:
query result in relaxed json format: {"_id": "6035210f35bd203721c3eab8", "name": "Gabriel García Márquez", "dateOfDeath": {"$date": "2014-04-17T04:00:00Z"}, "novels": [{"title": "One Hundred Years of Solitude", "yearPublished": 1967}, {"title": "Chronicle of a Death Foretold", "yearPublished": 1981}, {"title": "Love in the Time of Cholera", "yearPublished": 1985}]}
有关本节中提到的方法和类的详情,请参阅以下 API 文档:
BasicDBObject
BasicDBObject
类支持您使用 Java 类型访问和操作文档数据。由于存在以下限制,我们建议您避免使用该类,除非您要从旧驱动程序版本迁移应用程序:
BasicDBObject
未实现Map<K, V>
,因此缺乏Map
的数据访问和操作便利方法。它实现的是
DBObject
接口而不是类,因此无法在不破坏二进制兼容性的情况下扩展 API。这意味着,如果接口变更会破坏二进制兼容性,那么所有使用该接口的应用程序和类都需要重新编译,才能运行新版本而不会出现错误。
以下代码片段中,我们将展示如何实例化和构建示例 BasicDBObject
实例,该实例代表包含多种不同字段类型的文档:
BasicDBObject author = new BasicDBObject("_id", new ObjectId()) .append("name", "Gabriel García Márquez") .append("dateOfDeath", Date.from(LocalDate.of(2014, 4, 17).atStartOfDay(ZoneId.systemDefault()).toInstant())) .append("novels", Arrays.asList( new BasicDBObject("title", "One Hundred Years of Solitude").append("yearPublished", 1967), new BasicDBObject("title", "Chronicle of a Death Foretold").append("yearPublished", 1981), new BasicDBObject("title", "Love in the Time of Cholera").append("yearPublished", 1985)));
要将此文档插入到某一集合中,请使用 getCollection()
方法实例化一个集合,而此方法会将 BasicDBObject
类指定为 documentClass
参数。然后,按以下方法调用 insertOne 操作:
// MongoClient mongoClient = <code to instantiate your client>; MongoDatabase database = mongoClient.getDatabase("fundamentals_data"); MongoCollection<BasicDBObject> collection = database.getCollection("authors", BasicDBObject.class); InsertOneResult result = collection.insertOne(author);
成功执行插入操作后,可以使用以下代码从集合中检索示例文档数据:
import com.mongodb.client.model.Filters; // <MongoCollection setup code here> BasicDBObject doc = collection.find(Filters.eq("name", "Gabriel García Márquez")).first(); if (doc != null) { System.out.println("_id: " + doc.getObjectId("_id") + ", name: " + doc.getString("name") + ", dateOfDeath: " + doc.getDate("dateOfDeath")); BasicDBList novels = (BasicDBList) doc.get("novels"); if (novels != null) { BasicDBObject[] novelArr = novels.toArray(new BasicDBObject[0]); for (BasicDBObject novel : novelArr) { System.out.println("title: " + novel.getString("title") + ", yearPublished: " + novel.getInt("yearPublished")); } } }
提示
前面的代码样本使用辅助方法检查返回类型,并在无法转换字段值时引发异常。您可以调用 get()
方法来检索类型为 Object
的值并跳过类型检查。
输出结果应如下所示:
_id: 5fb5fad05f734e3794741a35, name: Gabriel García Márquez, dateOfDeath: Thu Apr 17 00:00:00 EDT 2014 title: One Hundred Years of Solitude, yearPublished: 1967 title: Chronicle of a Death Foretold, yearPublished: 1981 title: Love in the Time of Cholera, yearPublished: 1985
有关本节中提到的方法和类的详情,请参阅以下 API 文档:
总结
在本指南中,我们介绍了可用于处理 BSON 数据的类,包括以下主题:
描述可用于处理 MongoDB 文档的四个 Java 类以及为什么您可能更喜欢其中一个类。
为每个类提供了构建包含多种类型的文档、将它们插入集合以及检索/访问其类型化字段的用法示例。