在 Java 中读取 MongoDB 文档,哪个 Document 类最合适?

发布: (2026年1月11日 GMT+8 02:28)
9 min read
原文: Dev.to

Source: Dev.to

TL;DR

答案就在标题中——使用 Document

概述

BSON 是一种二进制序列化格式(类似于 protobuf),MongoDB 用它来实现高效的存储和网络传输。
与其在读取或写入字段时扫描并重写整个字节序列,不如使用 内存中的对象,它提供了方便的方法。

在服务器端,MongoDB 使用可变的 BSON 对象;在客户端,Java 驱动提供了多个实现 Bson 接口的类。

下面是 MongoDB Java 驱动中 五种文档类 的简要指南、它们的特性以及何时选择它们。

1. Document (大多数应用的推荐选择)

  • 类型Map(由 LinkedHashMap 支持,以保留插入顺序)
  • 关键特性
    • 松散类型:值是普通的 Java 对象(StringIntegerDate,……)
    • 灵活:易于处理结构动态的文档
    • Map API:提供所有标准的 Map 操作
  • 何时使用
    • 需要简洁、灵活且“开箱即用”的表示。
    • 不需要严格的 BSON 类型安全。

2. BsonDocument

  • 类型Map(同样由 LinkedHashMap 支持)
  • 关键特性
    • 类型安全:每个值必须是 BSON 库类型(BsonStringBsonInt32BsonDocument,……)
    • 更严格的 API:编译时安全,但代码更冗长
    • Map API:与 Document 相同,只是使用 BsonValue
  • 何时使用
    • 需要显式控制 BSON 类型(例如精确的类型处理,或与要求 BsonDocument 的 API 交互)。

3. RawBsonDocument

  • 类型:对 原始字节数组(BSON 文档)的不可变包装器
  • 关键特性
    • 不可变:变更操作会抛出 UnsupportedOperationException
    • 惰性解析:仅在访问时才解析数据——非常适合透传场景
    • 内存高效:不会创建中间的 Java 对象
    • 转换decode(codec) 可在需要时将其转换为其他文档类型
  • 何时使用
    • 需要在整体文档操作中实现最高的性能和内存效率。
    • 适用场景包括:
      • 读取文档后原样转发(例如变更流、客户端加密)。
      • 处理非常大的文档且不需要逐字段检查。
      • 高吞吐量的管道,解析开销成为瓶颈时。

4. JsonObject

  • 类型:对 JSON 字符串String)的简单包装器
  • 关键特性
    • 不实现 Map;它仅是一个字符串持有者,可选地进行验证。
    • 不进行解析——原始 JSON 保持不变。
    • 支持 MongoDB 扩展 JSON 格式。
  • 何时使用
    • 应用主要处理 JSON(例如 REST API、日志、以 JSON 形式持久化文档)。
    • 想避免在 Map 与 JSON 之间转换的开销。

5. BasicDBObject (遗留)

  • 类型:扩展自 BasicBSONObject 并实现 DBObject实现 Map)。
  • 关键特性
    • 仅为 向后兼容 MongoDB 驱动 3.0 之前的版本而存在。
    • 缺少现代 Map 的便利方法。
    • 可能导致二进制兼容性问题。
  • 何时使用
    • 正在迁移已经使用 BasicDBObject 的旧代码。
    • 不要在新开发中使用——驱动文档建议避免使用它。

类间转换

所有五个类都实现了 Bson 接口,因此可以在驱动操作中互换使用(尽管性能可能有所不同)。

From → To示例
JSON → BsonDocumentBsonDocument.parse(jsonString)
Raw bytes → other typeRawBsonDocument.decode(codec)
Document → BsonDocument使用 CodecRegistry/DocumentCodec(或 document.toBsonDocument(... )
BsonDocument → DocumentdocumentCodec.decode(bsonDocument.asBsonReader())
JsonObject → JSON stringjsonObject.getJson()
RawBsonDocument ↔ Document通过 Codec(例如 DocumentCodec)进行编码/解码

快速决策指南

要求首选类
通用、灵活、易于使用Document
需要严格的 BSON 类型安全BsonDocument
想要不可变的原始字节表示以提升性能RawBsonDocument
仅使用 JSON 字符串JsonObject
维护遗留代码(3.0 之前的驱动)BasicDBObject

摘要

  • Document 是大多数应用的默认选择——它在灵活性、简洁性和功能性之间取得了平衡。
  • 当需要编译时类型安全时,选择 BsonDocument
  • 对于高性能、内存高效的直通场景,使用 RawBsonDocument
  • 当你的工作流围绕原始 JSON 时,使用 JsonObject
  • 仅在遗留迁移时保留 BasicDBObject

所有类都可以通过驱动的 codec 相互转换,这使你可以先使用最方便的类型,随后根据性能或类型安全需求进行切换。

Overview

本文解释了 RawBsonDocumentDocument 在解析策略、内存使用和可变性方面的差异。它还比较了 Oracle 和 PostgreSQL 中类似概念的可用性,并强调了 MongoDB 对现代应用的优势。

RawBsonDocument vs. Document

RawBsonDocument

  • 解析策略 – 逐序读取 BSON 文档 顺序,检查每个字段的 类型名称,直到找到请求的键。
  • 字段处理 – 仅对匹配的字段使用 RawBsonValueHelper.decode 进行解码;所有其他字段 跳过,不进行解析。
  • 嵌套结构 – 对于嵌套的文档和数组,只读取它们的 大小,并将相应的字节范围包装成新的 RawBsonDocumentRawBsonArray 实例,内容保持为 原始字节
  • 性能 – 提供 快速的单字段查找,同时保持 内存高效 并使文档 不可变
  • 使用场景 – 适用于 大文档 但只需要少数字段,或大多数文档在不检查的情况下直接传递的情况。

Document

  • 解析策略 – 使用完全反序列化的 LinkedHashMap
  • 急切解析 – 在创建 Document 时,所有字段都会被解析为 Java 对象。
  • 字段访问containsKey 等查找只是普通的 HashMap 操作。
  • 可变性 – 文档 完全可变,支持 putremoveclear 等操作。
  • 内存使用 – 消耗更多内存,因为每个字段都被实例化为 Java 对象。
  • 使用场景 – 适用于 中小型文档、需要频繁访问多个字段,或文档需要经常修改的情况。

注意: Document 使用 RawBsonDocument 进行解析或字段访问,因为那样效率低下;这两个类的设计目标不同。

BSON‑like 支持在其他数据库中的实现

Oracle

  • 没有 BSON – Oracle 将 JSON 存储为 OSON(Oracle 的二进制 JSON 格式),而不是 BSON。
  • 最接近的等价物OracleJsonObjectOracleJsonValue 类型之一),可以作为 javax.json.JsonObject 暴露或映射到领域对象。
  • 效率 – OSON API 直接在底层字节上操作,而不需要完整解析文档。它维护一个 本地字典(字段名)、一个 排序的哈希码数组,以及 紧凑的字段‑ID/值偏移数组,使驱动能够通过二分查找 原位定位 字段。
  • JSON 文本 – 若需要 JSON 文本,只需调用 ResultSet.getString(),该方法会在客户端将 OSON 镜像转换为 JSON。

PostgreSQL

  • 没有原生的 Java JSON 对象 APIjsonjsonb 列通过 JDBC 驱动返回为 文本
  • 解析责任 – 应用程序必须使用独立的 JSON 库来解析返回的字符串。
  • 二进制存储 – 虽然 jsonb 在服务器端以二进制格式存储数据,但这种效率 不会 通过网络传输;客户端仍然收到文本,并在访问字段前进行完整解析。

MongoDB 的优势

  • 面向领域对象 – MongoDB 让你直接使用领域对象 无需中间 ORM 层
  • Document – 充当 文档对象模型 (DOM),提供灵活的 map‑style 访问和自然的 Java 接口。
  • 透明转换 – 驱动自动将网络上的 BSON 转换为可用的 Java 对象,使其能够在应用中立即使用。
Back to Blog

相关文章

阅读更多 »

我的 TicketDesk 系统

简介:在我的编程入门模块中,我用 Java 开发了一个 TicketDesk 系统,能够:- 跟踪工单 - 跟踪登录信息 - 提供基于角色的身份验证……