- 数据库
- NoSQL
- 嵌入式数据库
- 实时数据库
【免费下载链接】rxdb
The local-first database that runs on every JS runtime and replicates with your existing backend - no vendor, no lock-in - https://rxdb.info/
MongoDB RxStorage 是 RxDB 官方提供的一种 RxStorage 实现,它允许你使用 MongoDB 作为 RxDB 数据库的底层存储引擎,从而同时获得 MongoDB 的成熟生态与可扩展性,以及 RxDB 的实时同步能力。读完本文,你将掌握 MongoDB RxStorage 的安装接入方式、连接串配置、已知限制与源码级工作原理,并了解它如何与 MongoDB 复制插件配合构建完整的实时同步方案。
什么是 MongoDB RxStorage
RxDB 本身并不是一个自包含的数据库,它把数据真正存放的位置抽象为 RxStorage 接口。通过切换不同的 RxStorage 实现,RxDB 可以在浏览器、Node.js、React Native 等不同 JavaScript 运行时上使用完全不同的底层存储。MongoDB RxStorage 就是其中的一种服务端实现,它通过 MongoDB 官方的 Node.js 驱动(mongodb包)把 RxDB 的文档、索引、变更事件等全部落地到 MongoDB 中。
该存储被设计为可与任何形态的 MongoDB 配合工作:
- 普通的 MongoDB Server(独立部署);
- MongoDB Replica Set(副本集);
- Sharded MongoDB Cluster(分片集群);
- Atlas Cloud Database(云数据库)。
这意味着无论你的基础设施是自建机房还是云上托管,都可以把 MongoDB 作为 RxDB 的持久化层。需要说明的是,由于浏览器和移动端无法直接使用 MongoDB 的 wire protocol 连接副本集,MongoDB RxStorage 主要用于 Node.js 服务端场景。
当前版本的已知限制
在把 MongoDB RxStorage 引入生产环境之前,务必先了解它的三条边界(与 RxAttachment 等功能的取舍有关):
- 多 Node.js 服务器共享同一个 MongoDB 数据库目前不受支持。从源码看,实例的变更事件通过进程内的
Subject广播(见 rx-storage-instance-mongodb.ts 中的changes$),跨进程的 MongoDB Change Stream 监听代码在源码中被注释掉并标注为可能的 premium 功能,因此多服务器场景下的变更传播无法保证。 - RxAttachments(附件)目前不受支持。存储实例的构造函数会对 schema 进行校验,一旦检测到
schema.attachments存在就直接抛出错误'attachments not supported in mongodb storage, make a PR if you need that',getAttachmentData方法同样直接抛错。 - 不支持在 MongoDB 上做非 RxDB 的写入。RxDB 期望所有写入都经由自身完成并维护所需的元数据(如
_rev、_deleted、_meta.lwt),外部直接写入会破坏 RxDatabase 的一致性,导致未定义行为。但你可以随时从外部对 MongoDB 存储执行只读查询,这不会影响 RxDB 的正常工作。
快速上手:把 RxDB 接入 MongoDB
使用 MongoDB RxStorage 只需两个步骤。
第一步:安装 mongodb 驱动包
npm install mongodb --savemongodb是 MongoDB 官方的 Node.js 驱动。在本仓库中,它被声明为mongodb的依赖项(package.json 中为"mongodb": "^6.21.0 || ^7.0.0"),同时也是 RxDB 自身运行 MongoDB 相关测试和脚本时使用的驱动版本。
第二步:创建 RxDatabase 时启用 MongoDB RxStorage
import { createRxDatabase } from 'rxdb'; import { getRxStorageMongoDB } from 'rxdb/plugins/storage-mongodb'; const myRxDatabase = await createRxDatabase({ name: 'exampledb', storage: getRxStorageMongoDB({ /** * MongoDB connection string * @link https://www.mongodb.com/docs/manual/reference/connection-string/ */ connection: 'mongodb://localhost:27017,localhost:27018,localhost:27019' }) });核心要点:
getRxStorageMongoDB从rxdb/plugins/storage-mongodb子路径导入(该导出在 package.json 的./plugins/storage-mongodb映射中同时提供了require、import两种格式);connection参数接收标准的 MongoDB 连接字符串,示例中的多主机地址localhost:27017,27018,27019对应一个三节点副本集;- 返回的
RxStorageMongoDB实例实现了 RxDB 的RxStorage接口,在 rx-storage-mongodb.ts 中可以看到它通过createStorageInstance创建真实的存储实例,并在创建前调用ensureRxStorageInstanceParamsAreCorrect校验参数。
connection之外的完整设置项定义在 mongodb-types.ts:
export type MongoDBDatabaseSettings = { connection: MongoDBConnectionString; // 例如 'mongodb://localhost:27017' transactionOptions?: TransactionOptions; // 可选,MongoDB 驱动的事务选项 };源码级原理:MongoDB RxStorage 是如何工作的
理解底层实现有助于你在遇到问题时快速定位,也能帮助你评估它在生产环境中的行为。
文档存储与_id字段替换
MongoDB 使用_id作为默认主键,且其生成规则与 RxDB 的主键语义不同。为了不冲突,当 RxDB schema 的主键字段名为_id时,存储层会把它替换为内部字段__id(常量MONGO_ID_SUBSTITUTE_FIELDNAME,定义于 mongodb-helper.ts)。写入时swapRxDocToMongo把_id改名为__id,读取时swapMongoToRxDoc再把它还原为_id,查询与排序条件也会做同样的转换(primarySwapMongoDBQuerySelector、swapToMongoSort)。
集合命名与索引创建
每个 RxDB 存储实例会连接到名为databaseName + '-v' + schema.version的数据库(例如exampledb-v0),集合名即为 collectionName。实例创建时会自动:
createCollection创建集合;- 把 schema 中的
indexes数组展开,并为每个索引追加主键索引,然后调用createIndexes建立 MongoDB 索引(索引名由字段名以|连接而成,见getMongoDBIndexName)。
因此,你无需手工维护 MongoDB 侧索引,schema 定义即可驱动索引结构。
写入与冲突检测
由于 MongoDB 不支持跨文档事务(源码注释中明确说明),RxDB 采用"先比较前序版本再更新"的策略来保证一致性:
- 插入:通过
findOneAndUpdate配合$setOnInsert与upsert: true实现"不存在才插入";若文档已存在则产生一个status: 409的RxStorageWriteErrorConflict冲突错误; - 更新:通过
findOneAndReplace,查询条件中同时带上_rev前序修订号,只有版本匹配才会替换成功;若失败则重新读取当前文档并返回冲突错误。
所有写操作通过writeQueue串行排队执行,避免并发写互相踩踏(详见 rx-storage-instance-mongodb.ts 的bulkWrite实现)。这与 RxDB 的修订号(revision)机制一脉相承,确保了在无事务支持的 MongoDB 上也能可靠地检出写冲突。
查询、计数与清理
- 查询:RxDB 的 Mango 查询会被
prepareMongoDBQuery转换为 MongoDB 的 selector 与 sort,再依次应用skip、limit、sort,最终把结果逐条swapMongoToRxDoc还原为 RxDB 文档格式; - 计数:直接使用
countDocuments,并返回mode: 'fast'; - 清理:
cleanup通过deleteMany删除_deleted: true且_meta.lwt早于now() - minimumDeletedTime的墓碑文档,这是 RxDB 清理机制(Cleanup)在 MongoDB 上的落地实现。
客户端连接管理
getMongoDBClient/closeMongoDBClient(见 mongodb-helper.ts)维护了一个按连接串为 key 的MONGO_CLIENT_CACHE,对同一个连接串复用MongoClient实例,并以引用计数管理生命周期:引用归零后延迟 2 秒再真正关闭连接,以便短期复用场景避免反复建连。连接时还会通过driverInfo把驱动标识标记为RxDB及对应版本,便于在 MongoDB 侧观察流量来源。
与 MongoDB 复制插件的关系
MongoDB RxStorage 解决的是"数据存在哪",而 MongoDB 复制插件解决的是"数据如何与其他服务同步"。两者可以独立使用,也可以组合:复制插件基于 MongoDB Change Stream 实现双向实时同步,其客户端通过 RxServer 的复制端点与 MongoDB 通信;而 MongoDB RxStorage 则适合在 Node.js 服务端把 MongoDB 直接作为 RxDB 的存储引擎。组合使用时,你可以让 RxDB 直接读写 MongoDB,再借助复制插件把变更分发到其他客户端或系统。
测试与本地运行
仓库内置了 MongoDB 相关的完整测试与运维脚本(见 package.json):
- 启动本地 MongoDB 副本集(基于 Docker,mongo 8.0.4):
npm run mongodb:start该命令启动三个端口(27017/27018/27019)并以--replSet rs0模式运行,与文档示例中的三主机连接串对应。停止命令为npm run mongodb:stop。
- 连接自检:
node ./config/mongodb-connection-tester.js(config/mongodb-connection-tester.js)会等待容器启动、初始化副本集并等待主节点就绪后执行一次插入,供 CI 判断数据库是否可用; - 运行测试:
npm run test:node:mongodb # 以 mongodb 为默认存储运行 Node 端单元测试 npm run test:fast:mongodb # 快速模式测试(跳过 init 测试) npm run test:performance:mongodb测试配置位于 test/unit/config.ts,其中 MongoDB 存储的测试连接串为mongodb://localhost:27017/?directConnection=true,并标注了该存储的测试能力矩阵:hasPersistence: true、hasMultiInstance: false、hasAttachments: false、hasReplication: true——这与上文列出的限制完全一致,也是你评估功能覆盖范围的最直接依据。
生产使用建议
综合文档与源码,接入 MongoDB RxStorage 时有几点值得注意:
- 确保 MongoDB 可用性:写入依赖
findOneAndReplace与 upsert 语义,请确保使用的 MongoDB 版本支持这些操作;副本集模式下建议在连接串中配置多个节点以提升容错。 - 外部只读、内部独占写:让所有写入都经由 RxDB 完成,外部系统如需读取数据可直接查询 MongoDB,但不要绕过 RxDB 直接修改文档,否则会破坏
_rev与元数据的一致性。 - 避开不支持的子集:当前版本不要使用 attachments schema 字段,也不要部署多 Node.js 实例共享同一 MongoDB 数据库(这会绕开
hasMultiInstance: false的边界)。 - 善用 schema 驱动索引:索引由 RxDB 在集合创建时自动建立,新增查询字段时先在 RxDB schema 的
indexes中声明,以保证查询性能。
MongoDB RxStorage 让"本地优先 + 服务端 MongoDB"的架构成为可能:客户端获得 RxDB 的响应式查询与离线能力,服务端获得 MongoDB 的成熟存储与运维生态。结合上述限制与源码行为,你可以据此判断它是否适合你的项目场景。
- 数据库
- NoSQL
- 嵌入式数据库
- 实时数据库
【免费下载链接】rxdb
The local-first database that runs on every JS runtime and replicates with your existing backend - no vendor, no lock-in - https://rxdb.info/
相关推荐
RxDB RxStorage 层详解:为每种运行环境选择与组合最佳存储引擎
RxDB RxStorage 层详解:为每种运行环境选择与组合最佳存储引擎 RxStorage 是 RxDB 的存储抽象层,它把「数据库内核」与「底层存储引擎」
数据库NoSQL嵌入式数据库实时数据库RxDB Expo Filesystem RxStorage 实战指南:让 React Native 数据库读写超越 SQLite
RxDB Expo Filesystem RxStorage 实战指南:让 React Native 数据库读写超越 SQLite 本文以 RxDB 官方文档
数据库NoSQL嵌入式数据库实时数据库F3D:如何用极简工具实现专业级3D模型预览的完整指南
F3D:如何用极简工具实现专业级3D模型预览的完整指南 你是否曾为复杂的3D软件安装包而烦恼?是否在寻找一款能快速预览各种格式3D模型的轻量级工具?今天我将为你
数据库NoSQL嵌入式数据库实时数据库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考