使用ArangoDB实现多库连接及项目动态建库的技术方案咨询

实现思路
- 全局元数据层设计:设置中心元数据库统一存储所有团队、项目、对应业务数据库的映射关系,以及实例配置信息。SaaS模式下元数据库可单独部署做高可用,私有化部署时元数据库可与业务库共用同一ArangoDB实例,无需额外资源。
- 动态数据库创建逻辑:新团队创建项目时,先校验操作权限,通过后调用ArangoDB官方JS驱动
arangojs生成带唯一标识的数据库名(推荐规则proj_${项目UUID}避免命名冲突),同步为该库初始化默认集合、索引、内置基础数据,同时生成仅拥有该库操作权限的专属账号,禁止使用高权限账号操作业务库,保障数据安全。 - 多租户路由中间件:开发Express全局中间件,请求进入时先从JWT payload、请求头或者路径参数中解析项目ID,查询元数据库获取对应数据库连接配置后挂载到
req对象上,后续业务路由直接调用挂载的连接即可操作对应项目库,无需重复查询映射关系。 - 双模式适配逻辑:单独抽离配置模块,SaaS模式下自动连接统一的ArangoDB集群,私有化部署模式下读取用户本地配置文件中的ArangoDB实例地址,无需修改业务逻辑即可适配两种部署场景。
- 连接池管理:启用
arangojs自带的连接池配置,缓存高频访问项目的数据库连接,避免每次请求新建连接导致性能损耗,同时配置闲置连接定时回收规则,避免资源泄漏。
示例代码
依赖安装
npm install arangojs express jsonwebtoken dotenv uuid @types/express @types/node @types/jsonwebtoken @types/uuid typescript ts-node
1. 数据库连接配置(src/config/arango.ts)
import { Database } from "arangojs"; import dotenv from "dotenv"; dotenv.config(); // 中心元数据库连接 export const metaDb = new Database({ url: process.env.ARANGO_META_URL || "http://localhost:8529", auth: { username: process.env.ARANGO_META_USER || "root", password: process.env.ARANGO_META_PWD || "root", }, databaseName: "platform_meta", }); // 动态获取指定项目的数据库连接 export const getProjectDb = async (projectId: string) => { const projectMeta = await metaDb.collection("projects").document(projectId); // 适配双模式:优先读SaaS集群地址,私有化部署读本地配置地址 const dbHost = process.env.ARANGO_CLUSTER_URL || process.env.ARANGO_PRIVATE_URL; const db = new Database({ url: dbHost, auth: { username: projectMeta.dbUser, password: projectMeta.dbPwd, }, databaseName: projectMeta.dbName, poolSize: 10, // 连接池配置 }); return db; };
2. 动态创建项目库逻辑(src/services/project.service.ts)
import { metaDb } from "../config/arango"; import { Database } from "arangojs"; import { v4 as uuidv4 } from "uuid"; export const createProjectDb = async (teamId: string, projectName: string) => { const projectId = uuidv4(); const dbName = `proj_${projectId.replace(/-/g, "")}`; const dbUser = `user_${projectId.replace(/-/g, "")}`; const dbPwd = uuidv4(); // 生产环境建议用更复杂的密码生成规则 // 用实例root权限创建新库 const rootDb = new Database({ url: process.env.ARANGO_ROOT_URL, auth: { username: "root", password: process.env.ARANGO_ROOT_PWD }, }); // 创建数据库并分配专属账号 await rootDb.createDatabase(dbName, [{ username: dbUser, passwd: dbPwd, active: true, }]); // 初始化新库的默认集合、索引 const projectDb = rootDb.database(dbName); await projectDb.createCollection("documents"); await projectDb.collection("documents").ensureIndex({ type: "persistent", fields: ["createdAt"] }); // 可根据业务需求继续初始化其他集合、视图、内置数据 // 项目元数据写入中心库 await metaDb.collection("projects").save({ _key: projectId, teamId, projectName, dbName, dbUser, dbPwd, // 生产环境必须加密存储密码 createdAt: new Date(), }); return { projectId, dbName }; };
3. 多租户中间件(src/middleware/tenant.middleware.ts)
import { Request, Response, NextFunction } from "express"; import { getProjectDb } from "../config/arango"; import jwt from "jsonwebtoken"; // TS类型声明,扩展req对象 declare global { namespace Express { interface Request { projectDb: Database; projectId: string; } } } export const tenantMiddleware = async (req: Request, res: Response, next: NextFunction) => { try { const token = req.headers.authorization?.split(" ")[1]; if (!token) return res.status(401).send("未授权访问"); const payload = jwt.verify(token, process.env.JWT_SECRET as string) as any; const projectId = payload.projectId; // 挂载当前项目的数据库连接到req req.projectDb = await getProjectDb(projectId); req.projectId = projectId; next(); } catch (err) { return res.status(400).send("项目数据库连接失败,请确认项目是否存在"); } };
4. 业务路由示例(src/routes/documents.ts)
import express from "express"; import { tenantMiddleware } from "../middleware/tenant.middleware"; const router = express.Router(); // 所有当前路由下的接口都自动挂载对应项目的数据库连接 router.use(tenantMiddleware); // 查询当前项目下的所有文档 router.get("/", async (req, res) => { const docs = await req.projectDb.collection("documents").all(); res.json(await docs.all()); }); export default router;
部署兼容说明
- SaaS模式:ArangoDB采用集群部署,元数据库单独做高可用配置,项目数据库按存储容量自动分片,支持水平扩容应对租户增长。
- 私有化部署:打包时内置默认ArangoDB配置,用户可通过修改.env文件自定义数据库地址,支持对接用户自行部署的ArangoDB实例,所有数据均存储在用户本地服务器,符合企业数据安全要求。
内容的提问来源于stack exchange,提问作者kashyap
相关产品推荐
相关产品推荐

