尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

使用 Ubicloud 托管 Postgres 作为 FerretDB 后端:从建库到 Python 应用实战

发布时间:2026/9/23 18:48:35

资讯中心
01
ARTICLE

使用 Ubicloud 托管 Postgres 作为 FerretDB 后端:从建库到 Python 应用实战

使用 Ubicloud 托管 Postgres 作为 FerretDB 后端:从建库到 Python 应用实战
后端数据库文档数据库【免费下载链接】FerretDBA truly Open Source MongoDB alternative项目地址https://gitcode.com/gh_mirrors/fe/FerretDB点击查看免费下载本文讲解如何以 Ubicloud Managed Postgres 作为后端存储为 PostgreSQL 数据库叠加 MongoDB 兼容层 FerretDB并通过一个基于 Flask 与 pymongo 的联系人管理应用完成插入、查询、更新、删除的端到端验证。读完本文你将掌握 FerretDB 与托管 Postgres 的完整对接流程、mongosh连接认证方式以及如何在 psql 中直接检视 FerretDB 写入 Postgres 的 JSONB 数据。FerretDB 与 Ubicloud Managed Postgres为什么组合在一起FerretDB 是一个开源文档数据库它的核心定位是为 Postgres、SQLite 等关系型数据库后端“叠加”MongoDB 兼容能力应用继续使用 MongoDB 协议与 API数据却由成熟的 Postgres 存储与保障。这一组合在数据库成本与供应商锁定vendor lock-in问题上提供了更灵活的选择——你不需要被托管 MongoDB 服务的计价模型绑住数据始终掌握在自己手中。Ubicloud 是开放、可移植的云平台其 Managed Postgres 服务提供自动备份、时间点恢复point-in-time restore、每台 Postgres 服务器独立的专用虚拟机以及传输中和静态数据的加密。将 FerretDB 指向 Ubicloud Managed Postgres 后你得到的是一个“可在任何 Postgres 上迁移的 MongoDB 兼容数据库”这正是原文档强调的核心价值。版本提示原文档撰写于 2024 年 1 月当时 FerretDB 运行版本为 v1.18.0后端为 PostgreSQL 16.1直接对接普通 Postgres 即可。当前仓库v2 系列已演进为通过 PostgreSQL 的 DocumentDB 扩展提供服务且客户端认证仅支持SCRAM-SHA-256。本文保留原文档的完整实操流程并在对应小节标注当前仓库的差异以便两类用户都能按图索骥。准备工作Prerequisites开始前请确保具备以下条件Ubicloud Postgres 连接 URI连接字符串psql命令行工具Docker用于本地运行 FerretDB 容器mongoshMongoDB Shell用于连接 FerretDB。在 Ubicloud 上创建 Postgres 实例FerretDB 需要一个 Postgres 连接字符串作为后端。按照 Ubicloud 的托管 Postgres 快速入门文档创建实例后你会得到默认postgres用户的连接字符串格式如下postgres://postgres:passwordhost address接下来为 FerretDB 创建独立的数据库与专用账号。使用 psql 连接 Ubicloud Postgrespsql ubicloud-postgres-connection-string然后在 psql 中执行CREATE USER ferretuser WITH PASSWORD password; CREATE DATABASE ferretdb OWNER ferretuser; GRANT ALL PRIVILEGES ON DATABASE ferretdb TO ferretuser;这里创建的ferretuser账号与ferretdb数据库将贯穿后续所有步骤。为数据库建立专用账号而不是直接使用超级用户符合最小权限原则也让FERRETDB_POSTGRESQL_URL中的凭据边界清晰。运行 FerretDB连接字符串如何配置FerretDB 通过 PostgreSQL 连接 URL 定位后端数据库。在当前仓库中该参数对应的配置项定义在 配置文档Flag说明环境变量默认值--postgresql-urlPostgreSQL 连接 URLFERRETDB_POSTGRESQL_URLpostgres://127.0.0.1:5432/postgres--postgresql-url-file指向包含连接 URL 的文件非空时覆盖--postgresql-urlFERRETDB_POSTGRESQL_URL_FILE空每个命令行 Flag 都有对应的环境变量等价形式方便容器化与云原生部署。FerretDB 使用 pgx v5 库连接 PostgreSQL仓库文档同时注明pool_min_conns未设置时默认 10覆盖 pgx 的 0、pool_max_conns默认 50覆盖 pgx 的 4、application_name恒为FerretDB、timezone恒为UTC——这些默认值意味着托管实例的连接池配额至少要能容纳 FerretDB 的并发需求。现在将ferretuser的连接字符串整理为如下格式postgres://ferretuser:passwordpostgres-server-hostname/ferretdb在终端中拉取并运行 FerretDB 镜像把连接字符串通过FERRETDB_POSTGRESQL_URL环境变量注入容器docker run -e FERRETDB_POSTGRESQL_URLferretuser-connection-string ghcr.io/ferretdb/ferretdb若希望从宿主机访问可参照同类部署实践追加端口映射如-p 27017:27017这样mongosh即可通过127.0.0.1:27017访问容器内的 FerretDB。使用 mongosh 连接并验证版本FerretDB 启动成功后用mongosh连接实例。原文档写作时 FerretDB 支持 PLAIN 认证机制因此需要在 MongoDB URI 中显式声明mongosh mongodb://ferretuser:ferretuser-password127.0.0.1:27017/ferretdb?authMechanismPLAIN连接成功后可以看到类似如下的启动信息原文档基于 FerretDB v1.18.0 与 PostgreSQL 16.1Current Mongosh Log ID: 65afa52615e82bd1fc9d4371 Connecting to: mongodb://credentials127.0.0.1:27018/ferretdb?authMechanismPLAINdirectConnectiontrueserverSelectionTimeoutMS2000appNamemongosh2.1.0 Using MongoDB: 7.0.42 Using Mongosh: 2.1.0 ------ The server generated these startup warnings when booting 2024-01-23T11:38:17.837Z: Powered by FerretDB v1.18.0 and PostgreSQL 16.1. ... ferretdb当前仓库的认证机制差异需要特别说明的是认证机制的实现随版本演进已发生变化。当前仓库中客户端认证仅支持SCRAM-SHA-256机制saslStart/saslContinue命令注册于 内部命令表分发入口位于 cmd_query.go在 msg_saslstart.go 中若mechanism不是SCRAM-SHA-256服务端会直接返回机制不可用错误认证流程为 SCRAM 握手解析客户端首条消息 → 从 Postgres 查询用户的 salt 与迭代次数 → 生成服务端首条消息返回最终通过saslContinue完成握手。因此在 v2 系列上部署时应改用 SCRAM 兼容的认证方式连接例如直接使用带用户凭据的 URI默认即 SCRAM-SHA-256而不显式指定authMechanismPLAIN。完整的认证流程说明见 认证文档FerretDB 自身不存储任何用户凭据而是把客户端凭据转发给 PostgreSQL 校验匿名客户端虽可建立连接但无法访问数据库。用 Python 联系人应用做端到端测试进入ferretdb提示符后即可按 MongoDB 习惯操作数据。原文档使用一个 Flask 联系人应用基于pymongo验证基本 CRUD下面的代码与结构可直接照搬。搭建项目结构mkdir ContactApp cd ContactApp touch app.py mkdir templates touch templates/index.html templates/update.html首页模板 index.html!doctype html html langen head meta charsetUTF-8 / titleContact Book/title link relstylesheet hrefhttps://cdn.jsdelivr.net/npm/semantic-ui2.4.2/dist/semantic.min.css / script function confirmDelete(contact_id) { if (confirm(Are you sure you want to delete this contact?)) { document.getElementById(delete-form- contact_id).submit() } } /script /head body classui container h1Contact Book/h1 form action/add methodPOST classui form div classui form div classfour fields div classfield labelName/label input typetext namename placeholderName required / /div div classfield labelPhone/label input typetel namephone placeholderPhone / /div div classfield labelEmail/label input typeemail nameemail placeholderEmail / /div /div button classui green button typesubmitAdd Contact/button /div /form table classui celled table thead tr thName/th thPhone/th thEmail/th thActions/th /tr /thead tbody {% for contact in contacts %} tr td{{ contact[name] }}/td td{{ contact[phone] }}/td td{{ contact[email] }}/td td a href/update/{{ contact[_id] }} classui yellow button Update/a form iddelete-form-{{ contact[_id] }} action/delete/{{ contact[_id] }} methodpost styledisplay: inline; button typebutton onclickconfirmDelete({{ contact[_id] }}) classui red button Delete /button /form /td /tr {% endfor %} /tbody /table /body /html更新页模板 update.html!DOCTYPE html html langen head meta charsetUTF-8 titleContact Book/title link relstylesheet hrefhttps://cdn.jsdelivr.net/npm/semantic-ui2.4.2/dist/semantic.min.css /head body classui container h1Update Contact/h1 form action/update/{{ contact[_id] }} methodpost classui form div classui form div classfour fields div classfield input typetext namename value{{ contact[name] }} placeholderName required /div div classfield input typetel namephone value{{ contact[phone] }} placeholderPhone /div div classfield input typeemail nameemail value{{ contact[email] }} placeholderEmail /div button typesubmit classui green buttonUpdate Contact/button /div /form /div /body /html应用主逻辑 app.pyimport os from flask import Flask, render_template, request, redirect, url_for from pymongo import MongoClient from bson.objectid import ObjectId app Flask(__name__) mongo_uri os.getenv(MONGO_URI, mongodb://localhost:27017/) client MongoClient(mongo_uri) db client.ferretdb contacts_collection db.contacts app.route(/) def index(): contacts contacts_collection.find() return render_template(index.html, contactscontacts) app.route(/add, methods[POST]) def add_contact(): try: name request.form.get(name) phone request.form.get(phone) email request.form.get(email) contacts_collection.insert_one({name: name, phone: phone, email: email}) except Exception as e: message fAn error occurred: {e} return redirect(url_for(index)) app.route(/delete/contact_id, methods[POST]) def delete_contact(contact_id): try: contacts_collection.delete_one({_id: ObjectId(contact_id)}) except Exception as e: message fAn error occurred while deleting the contact: {e} return redirect(url_for(index)) app.route(/update/contact_id, methods[GET, POST]) def update_contact(contact_id): contact contacts_collection.find_one({_id: ObjectId(contact_id)}) if request.method POST: try: updated_data { name: request.form.get(name), phone: request.form.get(phone), email: request.form.get(email) } contacts_collection.update_one({_id: ObjectId(contact_id)}, {$set: updated_data}) except Exception as e: message fAn error occurred while updating the contact: {e} return redirect(url_for(index)) return render_template(update.html, contactcontact) if __name__ __main__: app.run(debugTrue)这段代码展示了 MongoDB 文档模型的关键体验insert_one、find、find_one、update_one、delete_one等操作对应用透明FerretDB 在背后把它们翻译为对 Postgres 的写入——这正是“为关系型后端叠加 MongoDB 兼容层”的含义。运行应用先通过环境变量注入 MongoDB 连接字符串再启动应用export MONGO_URImongodb://mongodb-URI python app.py向应用添加以下联系人James McArthur 093465729276 jamesmcarthuryahoo.com Desmond Eko 064357692721 ekogmail.com Christine Elle 046899553291 christianelleyahoo.com随后可以验证更新与删除功能例如通过更新按钮把Desmond Eko改为Andrew Eko或删除列表中的某条记录观察数据在页面上与 Postgres 中的同步变化。在 psql 中检视数据FerretDB 的 JSONB 存储FerretDB 把 MongoDB 文档存储为 Postgres 中的 JSONB 数据。使用 Ubicloud 的 Postgres 连接字符串连接 psql将搜索路径切到ferretdbschema 后即可查看psql postgres-connection-stringset search_path to ferretdb;ferretdb \dt List of relations Schema | Name | Type | Owner ------------------------------------------------------------- ferretdb | _ferretdb_database_metadata | table | ferretuser ferretdb | contacts_cedcb8f0 | table | ferretuser (2 rows) ferretdb table contacts_cedcb8f0; _jsonb --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- {$s: {p: {_id: {t: objectId}, name: {t: string}, email: {t: string}, phone: {t: string}}, $k: [_id, name, phone, email]}, _id: 65afb5c8f1f80562d49e2076, name: James McArthur, email: jamesmcarthuryahoo.com, phone: 093465729276} {$s: {p: {_id: {t: objectId}, name: {t: string}, email: {t: string}, phone: {t: string}}, $k: [_id, name, phone, email]}, _id: 65afb655f1f80562d49e2078, name: Christine Elle\t, email: christianelleyahoo.com, phone: 046899553291} {$s: {p: {_id: {t: objectId}, name: {t: string}, email: {t: string}, phone: {t: string}}, $k: [_id, name, phone, email]}, _id: 65afb5f1f1f80562d49e2077, name: Andrew Eko, email: ekogmail.com, phone: 064357692721} (3 rows) ferretdb观察这个输出可以提取出几个关键事实每个集合对应一张 Postgres 表此处为contacts_cedcb8f0FerretDB 维护一张_ferretdb_database_metadata元数据表整条 MongoDB 文档存放在单一_jsonb列中文档内的_id保留为 ObjectId 类型形如65afb5c8f1f80562d49e2076JSONB 中带有$sschema 描述$p为字段类型映射、$k为键顺序这正是 FerretDB 能够在关系型存储上还原 MongoDB 文档语义的实现细节更新操作Desmond Eko→Andrew Eko与删除操作都已正确反映在 Postgres 数据中。总结FerretDB 为 Ubicloud Managed Postgres 提供了一条低成本的 MongoDB 兼容路径数据由托管 Postgres 负责可靠性、备份与恢复应用侧则继续使用 MongoDB 协议与工具链。这套组合尤其适合已经运行在 Hetzner 数据中心、需要托管 Postgres 服务同时希望保留 MongoDB 开发体验、又不想被供应商锁定的团队。需要再次提醒的版本差异原文档基于 v1.18.0直接对接普通 Postgres、支持 PLAIN 认证当前仓库 v2 系列要求 Postgres 安装 DocumentDB 扩展客户端认证仅支持 SCRAM-SHA-256。部署前请先阅读仓库中的 认证文档、配置参数文档 与 Docker 安装文档根据实际版本选择匹配的连接方式与认证参数。赞分享后端数据库文档数据库【免费下载链接】FerretDBA truly Open Source MongoDB alternative项目地址https://gitcode.com/gh_mirrors/fe/FerretDB点击查看免费下载相关推荐使用 pgEdge 分布式 PostgreSQL 作为后端运行 FerretDB从 Docker 部署到 MongoDB CRUD 实战使用 pgEdge 分布式 PostgreSQL 作为后端运行 FerretDB从 Docker 部署到 MongoDB CRUD 实战 FerretDB 是后端数据库文档数据库使用 Airflow 构建端到端数据管道从 CSV 下载到 Postgres 清洗入库的完整实战使用 Airflow 构建端到端数据管道从 CSV 下载到 Postgres 清洗入库的完整实战 本文是 Apache Airflow 入门系列教程的第三篇后端任务调度工作流自动化数据编排批处理数据工程流程编排使用 Electric 对接 Supabase从托管 Postgres 到 Edge Function 的端到端同步指南使用 Electric 对接 Supabase从托管 Postgres 到 Edge Function 的端到端同步指南 导读 本指南以 Electric 官后端数据同步数据库人工智能AI AgentMCP 服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。