跳转到主要内容

文档 v3.7.0 版本已不再积极维护,你当前浏览的是一份归档快照。 最新文档请参阅 最新版本

FerretDB

MongoDB 线协议兼容的 PostgreSQL 方案

FerretDB 是开源的 MongoDB 线协议兼容中间件,可将 PostgreSQL 作为 MongoDB 的直接替代后端。依赖 MongoDB 线协议的应用可以通过它无缝使用 PostgreSQL,在两个数据库生态之间建立桥梁。

启用 FerretDB 需要使用 FerretDB 修订的 documentdb 扩展;Pigsty 软件仓库也提供该扩展。此冻结版本中的最新组合为 FerretDB 2.7 与 DocumentDB 0.107.0。


快速上手

按照 Pigsty 的标准安装流程,使用 mongo 配置模板:

./configure -c mongo    # 使用 FerretDB / DocumentDB 配置模板
./install.yml           # 安装;生产部署前请先修改 pigsty.yml 中的密码

生产部署时,务必在运行安装剧本前修改 pigsty.yml 中的密码参数。


配置

pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-meta
    pg_users:
      - { name: mongod      ,password: DBUser.Mongo  ,pgbouncer: true ,roles: [dbrole_admin   ] ,comment: ferretdb super user ,superuser: true }
      - { name: dbuser_meta ,password: DBUser.Meta   ,pgbouncer: true ,roles: [dbrole_admin   ] ,comment: pigsty admin user }
      - { name: dbuser_view ,password: DBUser.Viewer ,pgbouncer: true ,roles: [dbrole_readonly] ,comment: read-only viewer  }
    pg_databases:
      - {name: meta, owner: mongod ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ documentdb, postgis, vector, pg_cron, rum ]}
    pg_hba_rules:
      - { user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes' }
      - { user: mongod      , db: all ,addr: world ,auth: pwd ,title: 'mongodb password access from everywhere' }
    node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ]

    # DocumentDB 设置
    pg_extensions: [ documentdb, citus, postgis, pgvector, pg_cron, rum ]
    pg_libs: 'pg_documentdb, pg_documentdb_core, pg_cron, pg_stat_statements, auto_explain'
    pg_parameters: { cron.database_name: meta }

使用

完整说明请参阅 FERRET 模块文档。

安装客户端工具

可以使用 MongoDB 命令行工具 MongoSH 访问 FerretDB。

先用 pig 添加 MongoDB 软件仓库,再通过 yumapt 安装 mongosh

pig repo add mongo -u
yum install mongodb-mongosh
apt install mongodb-mongosh

连接 FerretDB

任何语言的 MongoDB 驱动都可以使用 MongoDB 连接串访问 FerretDB。以下为 mongosh 示例:

$ mongosh
Current Mongosh Log ID: 67ba8c1fe551f042bf51e943
Connecting to:          mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.0
Using MongoDB:          7.0.77
Using Mongosh:          2.4.0

For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/

test>

认证

可以使用不同用户登录,细节参阅 FerretDB:认证

mongosh 'mongodb://dbuser_meta:[email protected]:27017/meta'      # 业务管理员
mongosh 'mongodb://dbuser_view:[email protected]:27017/meta'    # 只读用户

使用示例

连接 FerretDB 后,可以像使用 MongoDB 集群一样执行命令:

$ mongosh 'mongodb://dbuser_meta:[email protected]:27017/meta'

MongoDB 命令会转换为 SQL,并在底层 PostgreSQL 中执行:

use test                            // CREATE SCHEMA test;
db.dropDatabase();                  // DROP SCHEMA test;
db.createCollection('posts');       // CREATE TABLE posts(_data JSONB,...)
db.posts.insertOne({                // INSERT INTO posts VALUES(...);
    title: 'Post One',body: 'Body of post one',category: 'News',tags: ['news', 'events'],
    user: {name: 'John Doe',status: 'author'},date: Date()}
);
db.posts.find().limit(2).pretty();  // SELECT * FROM posts LIMIT 2;
db.posts.createIndex({ title: 1 })  // CREATE INDEX ON posts(_data->>'title');

如果不熟悉 MongoDB,可以参考同样适用于 FerretDB 的 MongoDB Shell CRUD 教程

下面的 mongosh 脚本可用于生成简单的示例负载:

cat > benchmark.js <<'EOF'
const coll = "testColl";
const numDocs = 1000;

for (let i = 0; i < numDocs; i++) {
  db.getCollection(coll).insertOne({ num: i, name: "MongoDB Benchmark Test" });
}
for (let i = 0; i < numDocs; i++) {
  db.getCollection(coll).find({ num: i });
}
for (let i = 0; i < numDocs; i++) {
  db.getCollection(coll).updateOne({ num: i }, { $set: { name: "Updated" } });
}
for (let i = 0; i < numDocs; i++) {
  db.getCollection(coll).deleteOne({ num: i });
}
EOF

mongosh 'mongodb://dbuser_meta:[email protected]:27017' benchmark.js

FerretDB 的支持命令列表已知差异说明了兼容边界;对基本使用场景而言,这些差异通常影响不大。