You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 12:45:01