FerretDB v1.17.0 技术解析:无后端构建、$natural 排序与 listCollections 增强
2026/9/24 9:44:00 网站建设 项目流程
  • 后端
  • 数据库
  • 文档数据库

【免费下载链接】FerretDB

A truly Open Source MongoDB alternative

项目地址:https://gitcode.com/gh_mirrors/fe/FerretDB
点击查看免费下载

本篇技术指南以 FerretDB 官方 v1.17.0 发布说明(website/blog/2023-12-19-ferretdb-releases-v117.md)为核心展开,系统讲解该版本带来的两大核心新特性——通过 Go 构建标签编译出无 PostgreSQL/SQLite 后端的 FerretDB、以及$natural排序与集合 UUID 生成,并逐一拆解listDatabasesvalidatelistCollections等命令的修复与字段增强。读完本文,你将掌握 v1.17.0 的发布全貌,并能理解这些能力在当前 FerretDB 代码库中的落点与演进脉络。

一、版本背景:2023 收官之发布

v1.17.0 是 FerretDB 在 2023 年("impressive year")的收官版本。回顾这一年,FerretDB 围绕"把 MongoDB 工作负载带回开源"这一使命取得了多项进展:新增 SQLite 后端、重构架构以支持更多后端(包括 MySQL 与 SAP Hana)、显著改善性能、提升对更多应用与使用场景的兼容性、并登陆多家托管云平台。与此同时,官方文档体系也经历了大规模改进,并在该版本启用了文档版本化(versioning)机制——这一点在当前仓库中依然可见,例如 website/versioned_docs 下按version-v1.24version-v2.5version-v2.7组织的多版本文档目录,以及 website/versioned_sidebars 中对应的版本化侧边栏文件。

本次发布还新增了 3 位贡献者(wazir-ahmed、anunayasri、hungaikev),社区规模持续扩大。

二、核心新特性:无后端构建(ferretdb_no_postgresql / ferretdb_no_sqlite)

v1.17.0 最重要的一项能力,是允许构建不带任何后端的 FerretDB:通过设置ferretdb_no_postgresqlferretdb_no_sqlite两个 Go 构建标签(build tags),可以分别或同时剔除 PostgreSQL 与 SQLite 后端,最终产出一个"无后端"的二进制。这为嵌入式使用、后端自研或仅需协议层/API 层的场景提供了极大的编译期灵活性。

2.1 构建标签的语义与用法

在 Go 中,构建标签通过//go:build约束(build constraints)在编译期生效,典型用法如下:

# 仅剔除 PostgreSQL 后端(保留 SQLite) go build -tags ferretdb_no_postgresql ./cmd/ferretdb # 仅剔除 SQLite 后端(保留 PostgreSQL) go build -tags ferretdb_no_sqlite ./cmd/ferretdb # 同时剔除两个后端,构建"无后端"版本 go build -tags "ferretdb_no_postgresql ferretdb_no_sqlite" ./cmd/ferretdb

这种机制意味着 FerretDB 从"双后端绑定"演进为"后端按需编译",天然支持未来接入 MySQL、SAP Hana 等更多后端,而不会让单一二进制体积与依赖无限膨胀。

2.2 构建标签机制在当前仓库中的落点

从当前仓库的源码看,构建标签(Go build tags)是 FerretDB 构建体系中的一等公民。在 build/version/version.go 的包级文档中,专门设有 "Go build tags" 一节,系统列出了会影响 FerretDB 构建的标签及其语义,例如:

  • ferretdb_dev—— 启用开发构建(启用 race detector 的构建会隐式带上),开发构建行为差异包括:显著更慢、部分随机值被固定以便调试、部分内部错误直接崩溃、更激进地收集堆栈、退出时向 stderr 输出指标、默认日志级别为 debug。

需要说明的是,当前仓库属于 v2 代码线,其build/version/version.go中正式文档化的构建标签列表为ferretdb_dev等;从当前构建约束搜索结果看,仓库中还使用ferretdb_bw(见 build/ferretdb-bw/ferretdb/ferretdb.go)与ferretdb_testenvdata(见 integration/shareddata_test.go)等标签,而 v1.17.0 时代引入的ferretdb_no_postgresql/ferretdb_no_sqlite已不在当前列表之中。可以推断:后端编译开关机制在后继版本中经历了演进与重构,但"以构建标签控制编译范围"这一设计思路被完整保留了下来。

2.3 与嵌入式能力的呼应

无后端构建的意义与 FerretDB 的嵌入式形态互为表里。在 ferretdb/ferretdb.go 中,ferretdb包被明确注释为 "embeddable FerretDB implementation"(嵌入式实现),其包级文档还专门引导读者查阅build/version包文档以了解影响该包的 Go 构建标签(见 ferretdb/ferretdb.go)。开发者既可以通过Config结构体(如PostgreSQLURLListenAddrStateDirLogLevelLogOutputTelemetry等字段)以库的形式嵌入 FerretDB,也可以通过构建标签裁剪后端依赖——两者结合,让"按需裁剪、按需嵌入"成为可能。

三、新特性:$natural 排序支持

v1.17.0 为查询增加了对$natural排序的支持:用户现在可以对 capped collection 使用{$natural: 1}{$natural: -1},按 RecordID 进行物理顺序的正向/逆向扫描。

3.1 什么是 $natural 排序

在 MongoDB 语义中,$natural排序不依赖任何索引,而是按照文档在存储介质中的物理顺序返回结果;对于 capped collection 这类天然有序的集合,$natural排序是常见且高效的操作方式:

// 按物理存储顺序(正序)读取 capped collection db.cappedCollection.find().sort({ $natural: 1 }) // 按物理存储顺序(倒序)读取 capped collection,通常用于读取最新写入的文档 db.cappedCollection.find().sort({ $natural: -1 })

v1.17.0 在 FerretDB 中实现了这一语义:{$natural: 1}{$natural: -1}按 RecordID 排序,仅适用于 capped collection,为依赖该特性的应用(如日志、事件流、操作日志类场景)补齐了兼容性。

值得一提的是,"capped collection + 有序读取"这一组合在 FerretDB 生态中有其实际用例:例如 website/versioned_docs/version-v1.24/configuration/oplog-support.md 中即说明,OpLog 作为 capped collection 以避免数据无界增长。可以推断,v1.17.0 的$natural排序支持为后续 OpLog 等有序场景的实现铺平了道路。

3.2 使用前提与限制

  • $natural排序仅适用于 capped collection;
  • 排序键必须是$natural,取值为1(正序)或-1(倒序);
  • 其底层对应 RecordID 的物理顺序,而非字段值顺序。

四、新特性:集合 UUID 生成并在 listCollections 中可见

v1.17.0 启用了集合 UUID(collection UUID)的生成,并使其在listCollections命令的输出中可见。UUID 是 MongoDB 中每个集合的稳定唯一标识,客户端(如驱动、GUI 工具)常通过它跟踪集合身份,即便集合被重命名也不会改变。

启用该特性后,listCollections返回的集合条目中会携带对应的 UUID 字段,应用侧可以据此实现与 MongoDB 一致的集合身份识别逻辑。

五、Bug 修复与增强

5.1 修复:listDatabases 在 nameOnly 参数下的过滤错误

v1.17.0 修复了listDatabases命令在传入nameOnly参数时的过滤错误。nameOnly用于仅返回数据库名称(而非完整信息对象),此前在该参数下过滤逻辑存在缺陷,会导致结果不符合预期。修复后,nameOnly模式下的数据库列表过滤行为与 MongoDB 保持一致。

该命令的实现在当前仓库中对应 internal/handler/msg_listdatabases.go,并在 internal/handler/commands.go 附近的命令注册表中以"listDatabases"注册。集成测试方面,可在 integration/commands_administration_test.go 中找到对该命令行为的覆盖。

5.2 增强:validate 诊断命令改进

v1.17.0 对validate诊断命令进行了改进。validate用于检查集合/数据库内部结构的完整性,其实现对应当前仓库中的 internal/handler/msg_validate.go。改进后的validate能够提供更准确的诊断信息,帮助运维与开发人员定位数据层面的异常。

5.3 增强:listCollections.cursor 响应字段扩展

v1.17.0 为listCollections命令的cursor响应新增了更多字段,包括:

字段说明
options.capped是否为 capped collection
options.sizecapped collection 的最大字节大小
options.maxcapped collection 的最大文档数量
info.readOnly集合是否为只读
idIndex集合的_id索引信息

这些字段让listCollections返回的元数据更加完整,客户端可以一次性获取集合的容量约束、只读状态与索引信息,减少额外的元数据查询。

从当前仓库的实现看,listCollections的调用链为:msgListCollections从请求文档中解析$db数据库名(见 internal/handler/msg_listcollections.go),通过CreateOrUpdateByLSID处理会话(LSID)后,调用h.p.ListCollections(connCtx, dbName, req.DocumentRaw())获取首页数据与游标 ID,再通过会话注册表h.s.AddCursor管理游标,最后以middleware.ResponseDoc返回分页响应。其中游标化的分页机制同样应用于 internal/documentdb/pool_cursors.go 中ListCollections的实现——"返回listCollections游标首页及游标 ID"。这一调用链说明,listCollections的响应字段增强不仅体现在 v1.17.0 发布时点,其游标化、会话化的架构在后继版本中一直延续。

六、总结

FerretDB v1.17.0 是一个"承前启后"的版本:

  • 构建层面:通过ferretdb_no_postgresql/ferretdb_no_sqlite构建标签实现了无后端构建,让后端以可插拔方式接入,呼应了 MySQL、SAP Hana 等多后端的架构演进方向;
  • 查询层面$natural排序为 capped collection 补齐了物理顺序扫描能力,集合 UUID 生成则提升了与 MongoDB 客户端生态的兼容性;
  • 命令层面:修复listDatabasesnameOnly过滤问题,改进validate诊断命令,并大幅扩展listCollections.cursor的元数据字段。

对于希望深入研究的读者,建议继续阅读以下仓库文件:v1.17.0 官方发布说明 website/blog/2023-12-19-ferretdb-releases-v117.md、构建标签机制文档 build/version/version.go、嵌入式 API 定义 ferretdb/ferretdb.go、listCollections命令实现 internal/handler/msg_listcollections.go 以及命令注册表 internal/handler/commands.go。

  • 后端
  • 数据库
  • 文档数据库

【免费下载链接】FerretDB

A truly Open Source MongoDB alternative

项目地址:https://gitcode.com/gh_mirrors/fe/FerretDB
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询