基于 Oracle Database 构建 Mastra 存储与向量检索:@mastra/oracledb 全解析
2026/9/15 11:43:55 网站建设 项目流程

基于 Oracle Database 构建 Mastra 存储与向量检索:@mastra/oracledb 全解析

【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra

导读

@mastra/oracledb是 Mastra 官方提供的 Oracle Database 存储与向量检索 Provider。它利用 Oracle 原生 JSON、VECTOR数据类型、连接池与事务能力,为 Mastra Agent 提供**存储(Storage)向量相似度搜索(Vector Search)**双引擎能力。本文基于仓库 stores/oracledb 的 README 与源码实现,系统讲解其安装、连接配置、存储 API、向量索引与检索、Schema 管理及本地测试方案,帮助你快速将 Oracle 数据库接入 Mastra 应用,并在生产环境中正确使用 Oracle 向量搜索。


一、认识 @mastra/oracledb

Mastra 是一个面向 AI 应用与 Agent 的 TypeScript 框架,@mastra/oracledb是它官方的 Oracle Database 数据层集成包。包的核心能力在 README.md 中定义:基于 Oracle JSON、OracleVECTOR数据类型、连接池(connection pooling)与事务支持,提供存储和向量相似度搜索

从包结构上看,它实际导出两大对象(见 src/index.ts):

  • OracleStore:Mastra 通用存储实现,负责线程(thread)、消息(message)、资源(resource)、工作流快照、可观测性(spans/logs)、评分(scores)、MCP 客户端注册与 Agent 注册等多个存储域;
  • OracleVector:Mastra 向量存储实现,基于 Oracle 23ai 的VECTOR数据类型与向量索引(HNSW / IVF),提供 upsert、query、delete、update 等向量 API。

两者共用同一个 OraclePoolManager 连接池管理器,共享生命周期。另外还导出:

  • ORACLEDB_PROMPT:供 LLM 构造合法向量过滤条件的提示词模板;
  • OracleConnectionConfig等类型;
  • 完整的 schema 导出工具exportSchemas

前置条件:该包依赖oracledb ^6.10.0(node-oracledb),要求 Node.js >= 22.13.0(见 package.json)。向量功能依赖 Oracle Database 23ai 的VECTOR类型;存储功能兼容更广泛的 Oracle 版本,但以 23ai 为推荐基线。


二、安装

在 Mastra 项目中安装:

npm install @mastra/oracledb

包的类型定义与运行时入口见 package.json 的exports字段:import对应 ESM 构建dist/index.jsrequire对应 CJS 构建dist/index.cjs,同时导出./package.json

包以@mastra/core(>=1.61.0-0, <2.0.0-0)作为 peer 依赖,使用时需确保核心包版本匹配。仓库内的集成测试还提供了 Docker 一键启动 Oracle Free 23ai 的方式(详见下文"本地测试"一节),可作为本地开发环境的参考。


三、连接配置与连接池

3.1 OracleStore 基础用法

README 中的最小示例(存储部分):

import { OracleStore } from '@mastra/oracledb'; const store = new OracleStore({ id: 'oracle-store', user: process.env.ORACLE_DATABASE_USER, password: process.env.ORACLE_DATABASE_PASSWORD, connectString: process.env.ORACLE_DATABASE_CONNECT_STRING, }); await store.init(); const memory = await store.getStore('memory'); if (!memory) throw new Error('Oracle memory store is not available'); // 创建线程 await memory.saveThread({ thread: { id: 'thread-123', resourceId: 'resource-456', title: 'My Thread', metadata: { key: 'value' }, createdAt: new Date(), }, }); // 向线程追加消息 await memory.saveMessages({ messages: [ { id: 'msg-789', threadId: 'thread-123', role: 'user', content: { content: 'Hello' }, resourceId: 'resource-456', createdAt: new Date(), }, ], }); // 查询线程与消息 const savedThread = await memory.getThreadById({ threadId: 'thread-123' }); const { messages } = await memory.listMessages({ threadId: 'thread-123' });

await store.init()会触发一次幂等的 schema 迁移(migration),随后即可通过store.getStore('memory')获取内存域进行操作。

3.2 连接参数全表

OracleConnectionConfig定义于 src/shared/connection.ts,包含以下字段:

参数类型说明
userstring数据库用户名。使用externalAuth时可省略
passwordstring数据库密码。使用externalAuth时可省略
connectStringstring连接串(host:port/service_name),必填(除非传入pool
poolPool外部传入的 node-oracledb 连接池;传入后由外部管理生命周期
poolMinnumber池最小连接数,默认0
poolMaxnumber池最大连接数,默认4
poolIncrementnumber池扩容步长,默认1
configDirstringOracle Wallet / TNS 配置目录(可选)
walletLocationstringOracle Wallet 目录(可选)
walletPasswordstringWallet 密码(可选)
externalAuthboolean启用外部认证(OS / Kerberos / Wallet TLS),此时可省略用户名密码

校验规则(validateOracleConnectionConfig):

  • 若未传入pool,则必须提供connectString,且除非externalAuth为 true 否则必须提供user
  • 除非externalAuth开启,否则password必填。

3.3 连接池生命周期

OraclePoolManager采用懒加载 + Promise 记忆化策略:首次getPool()时才调用oracledb.createPool(),创建失败会重置内部 Promise,避免一次性故障永久污染管理器(见 connection.ts)。

withConnection(callback)负责连接的获取与归还,事务所有权仍归调用方——它只管理 acquire/release(见 connection.ts)。

OracleStoreOracleVector都支持两种池管理方式:

  1. 自建池:不传poolManager,由 Provider 内部创建;调用disconnect()/close()时自动关闭池;
  2. 共享池:通过poolManager注入同一个OraclePoolManager实例,让存储与向量共享一个连接池,并由外部统一管理生命周期(ownsPool为 false 时close()不会关闭外部池)。

从源码结构可以推断:生产环境推荐共享池模式——OracleStoreOracleVector各自只持有一个OraclePoolManager引用,共享后能显著减少连接数。


四、OracleStore:存储域与自动迁移

4.1 七个存储域

OracleStore继承 Mastra 的MastraCompositeStore,构造时一次性装配 7 个存储域(见 src/storage/index.ts):

职责
memory线程、消息、资源、工作记忆(working memory)、观测记忆(observational memory)
workflows工作流快照(durable workflow 状态)
observabilityspans 与日志事件(Mastra 可观测性)
scores评分与评估结果
scorerDefinitionsScorer 定义注册表
mcpClientsMCP 客户端注册表
agentsAgent 注册表

每个域均为独立的 Oracle 领域实现(如MemoryOracleWorkflowsOracle),共享同一个OraclePoolManager,从而保证连接池统一、域间隔离。

4.2 自动迁移机制

init()触发幂等迁移:runMigrations依次执行 7 个 repeatable 迁移(R001_MEMORY_SCHEMA 到 R007_AGENTS_SCHEMA),每个迁移声明自己管理的表集合(MANAGED_TABLES),迁移内容为对应域的init()DDL(见 src/storage/index.ts)。

迁移是可重复执行的(repeatable类型):每次运行都会计算包含索引配置在内的 SHA-256 校验和(domainMigrationChecksum),当 DDL 或索引配置变化时才会重新应用。迁移记录写入migrationTableName(默认常量见DEFAULT_ORACLE_MIGRATIONS_TABLE),多个逻辑 Mastra 部署共享同一 Oracle schema 时可覆盖该表名。

DDL 执行封装在 connection.ts 的executeDdl中:对 Oracle 在线 DDL 常见的锁冲突错误码(-54、-14411)采用 100ms 到 1500ms 的指数退避重试。

4.3 OracleStoreConfig 配置项

OracleStoreConfig定义于 src/storage/types.ts,除连接参数外还包括:

参数说明
id存储实例标识
schemaName目标 Oracle schema 名(默认当前用户 schema)
poolManager共享连接池管理器(可选)
messageBatchSize每次executeMany写入的消息条数;整个saveMessages在事务边界只提交一次
skipDefaultIndexes为 true 时不创建默认性能索引(适合 DBA 单独管理索引的场景)
indexes初始化时创建的 Oracle 原生自定义索引列表,按目标表路由到所属域
migrationTableName迁移记录表名(多部署共享 schema 时覆盖)
vectorRegistryTableNameOracleVector.registryTableName一致时,用于消息/线程删除时发现语义召回向量表
disableInit禁用自动初始化(继承自MastraCompositeStoreConfig

4.4 CLOB 与 JSON 的底层处理

Mastra 的富文本字段(消息 content、instructions、workingMemory、observational memory 等)在 Oracle 中存储为CLOB;查询时通过fetchInfo配置将这些 CLOB 以字符串形式拉取,简化领域映射(见 connection.ts)。

JSON 字段使用 Oracle 原生 JSON 类型。写入时,jsonBind将 JSON 对象序列化为文本后绑定为DB_TYPE_VARCHAR由服务端编码为 OSON 二进制格式(见 connection.ts)。源码注释指出:若由 node-oracledb 瘦驱动客户端编码,其生成的 OSON 头部标志会导致 DBeaver/DataGrip/SQL Developer 渲染报UnsupportedOperationException,因此特意将编码移到服务端——这保证了第三方工具的可读性。

此外,safeJsonStringify会递归清理运行时对象:丢弃函数、symbol、循环引用,bigint 转为字符串,确保 JSON 列只写入 JSON 安全值。


五、OracleVector:向量索引与检索

5.1 快速上手

import { OracleVector } from '@mastra/oracledb'; const vector = new OracleVector({ id: 'oracle-vector', user: process.env.ORACLE_DATABASE_USER, password: process.env.ORACLE_DATABASE_PASSWORD, connectString: process.env.ORACLE_DATABASE_CONNECT_STRING, }); // 创建索引(dimension 与向量维度一致) await vector.createIndex({ indexName: 'my_vectors', dimension: 1536, metric: 'cosine', indexConfig: { type: 'hnsw', accuracy: 95 }, metadataIndexes: ['thread_id', 'resource_id'], }); // 写入向量 await vector.upsert({ indexName: 'my_vectors', vectors: [[0.1, 0.2, ...]], metadata: [{ thread_id: 't1', text: 'hello' }], }); // 查询(精确 / 近似检索) const results = await vector.query({ indexName: 'my_vectors', queryVector: [0.1, 0.2, ...], topK: 10, filter: { thread_id: 't1' }, queryMode: 'approx', });

5.2 向量索引模型

OracleVector的数据模型(见 src/vector/ddl.ts)由三层组成:

  1. 逻辑索引:面向 Mastra 的 API 名称(indexName);
  2. 物理表:每个逻辑索引对应一张专用VECTOR表,表名 =tablePrefix+ 索引名规范化后的结果(默认前缀MASTRA_VEC,见DEFAULT_TABLE_PREFIX)。表结构为vector_idembedding VECTOR(dimension, format)metadata JSON、时间戳列;
  3. 注册表MASTRA_VECTOR_INDEXESDEFAULT_REGISTRY_TABLE)记录逻辑索引到物理对象的映射(index_name、table_name、dimension、metric、index_type、vector_format、accuracy 等),是映射的"事实来源"(source of truth)。

5.3 索引类型、向量格式与度量

相关类型定义见 src/vector/types.ts:

  • 索引类型OracleVectorIndexTypehnsw|ivf|nonenone表示不建近似索引,仅用精确VECTOR_DISTANCE搜索;
  • 向量格式OracleVectorFormatvector(默认,float32 向量)|bit(二进制向量)|int8(量化向量);
  • 度量OracleMetriccosine|euclidean|dotproduct|hamming|jaccard
  • 查询模式OracleQueryModeapprox(近似检索)|exact(精确检索)。

OracleVectorIndexConfig支持:

{ type?: 'hnsw' | 'ivf' | 'none', accuracy?: number, // 目标精度,默认 95(%) hnsw?: { neighbors?: number, efConstruction?: number }, ivf?: { neighborPartitions?: number }, }

创建索引时默认accuracy: 95createIndex支持vectorFormatindexConfigbuildIndex(是否同步创建物理向量索引,默认 true)与metadataIndexes(为常见元数据字段创建JSON_VALUE函数索引,默认thread_idresource_idmessage_idsource_id,见DEFAULT_METADATA_INDEXES)。

物理索引 DDL 形态(由vectorPhysicalIndexStatement生成,见 schema.ts):

CREATE VECTOR INDEX ... ON ... (embedding) ORGANIZATION INMEMORY NEIGHBOR GRAPH -- HNSW -- 或 ORGANIZATION NEIGHBOR PARTITIONS -- IVF DISTANCE COSINE WITH TARGET ACCURACY 95

IndexRegistry内部还维护每个逻辑索引一把锁indexLocks),防止两个调用方并发创建/删除同一索引;并提供索引元数据缓存(indexInfoCache)减少重复查询。

5.4 写入路径:upsert / update / delete

  • upsert:默认每批 200 条向量(DEFAULT_VECTOR_UPSERT_BATCH_SIZE,可用upsertBatchSize覆盖),使用executeMany批量写入;deleteFilter+ upsert 在同一事务内完成,避免索引部分刷新(见 src/vector/upsert.ts);
  • 不传ids时自动生成 UUID;
  • updateVector/deleteVector/deleteVectors均基于vector_id与元数据过滤条件实现;
  • 当前版本不支持稀疏向量sparseVector/sparseVectors会直接报错),仅支持稠密向量。

5.5 查询路径:精确与近似检索

查询实现在 src/vector/query.ts:

  • 核心距离计算使用VECTOR_DISTANCE(embedding, :queryVector, <metric>),再转换为 Mastra 的 score 语义;
  • 默认查询模式:indexType === 'none'时为exact,否则为approx;可通过queryMode显式覆盖;
  • filter通过buildMetadataWhereClause编译为 SQL 谓词,支持纯元数据召回(不传 queryVector 时);
  • 支持minScore(默认 -1)过滤与includeVector(返回 embedding 原文);
  • Oracle 近似检索要求ORDER BYFETCH位于同一查询块,实现遵循该约束以保证走索引。

5.6 元数据过滤:支持的运算符

元数据存储为 Oracle JSON。ORACLEDB_PROMPT(见 src/vector/prompt.ts)明确定义了可用的过滤运算符与编译规则,并随包导出,供 Agent 在生成过滤条件时遵循:

编译规则

  • 标量比较 →JSON_VALUE(metadata, ...)
  • 数组/存在性/元素匹配 →JSON_EXISTS(metadata, ...)
  • 正则 → OracleREGEXP_LIKE
  • 字符串包含 → 大小写不敏感的LIKE
  • 所有用户元数据值一律作为绑定参数,不允许在过滤器中内嵌原始 SQL。

运算符清单

类别运算符说明示例
比较$eq精确匹配(默认){ "category": "electronics" }
$ne不等于{ "category": { "$ne": "electronics" } }
$gt/$gte大于 / 大于等于{ "price": { "$gt": 100 } }
$lt/$lte小于 / 小于等于{ "price": { "$lt": 100 } }
数组$in/$nin属于 / 不属于{ "category": { "$in": ["electronics", "books"] } }
$all数组包含全部{ "tags": { "$all": ["premium", "sale"] } }
$elemMatch数组元素满足条件{ "items": { "$elemMatch": { "price": { "$gt": 100 } } } }
$contains字符串子串 / 数组包含{ "title": { "$contains": "oracle" } }
逻辑$and/$or与 / 或{ "$or": [{ "price": { "$lt": 50 } }, ...] }
$not/$nor非 / 或非{ "$not": { "category": "electronics" } }
元素$exists字段是否存在{ "rating": { "$exists": true } }
特殊$size数组长度{ "tags": { "$size": 2 } }
$regex正则(REGEXP_LIKE){ "source": { "$regex": "oracle.*database" } }

使用限制(来自ORACLEDB_PROMPT):

  • 嵌套字段使用点号(dot notation)访问;
  • 顶层只能使用逻辑运算符($and/$or/$not/$nor),其余运算符必须位于字段条件内;
  • 逻辑运算符只能出现在顶层或嵌套在其他逻辑运算符中,不能位于字段内部;
  • $not必须是非空对象,可用于字段级或顶层;
  • $elemMatch必须接收带条件的对象。

5.7 运维与诊断 API

  • configureVectorMemory({ size, scope }):为本地/自管数据库配置 Vector Pool 内存(MEMORY|SPFILE|BOTH),HNSW 构建前需要;
  • getIndexStatus({ indexName }):查看索引稳态 catalog 状态;
  • indexAccuracyQuery({ indexName, queryVector, topK, targetAccuracy }):近似索引的精度诊断;
  • listIndexes()/describeIndex():枚举与描述索引;
  • disconnect()/close():释放连接池。

六、Schema 导出:面向 DBA 的离线 DDL

exportSchemas()(见 src/schema.ts)可离线导出与运行时迁移完全一致的 DDL,供 DBA 审阅或预建 schema:

import { exportSchemas } from '@mastra/oracledb'; const sql = exportSchemas({ schemaName: 'MASTRA', domains: ['memory', 'workflows', 'observability', 'vector'], vector: { indexes: [ { indexName: 'doc_embeddings', dimension: 1536, metric: 'cosine', indexConfig: { type: 'hnsw', accuracy: 95 } }, ], }, }); console.log(sql);

ExportOracleSchemasOptions支持schemaNamedomains(migrations/memory/workflows/observability/scores/scorerDefinitions/mcpClients/agents/vector)、skipDefaultIndexesindexes(自定义索引)与vector配置。域输出顺序固定:migrations → 存储域 → vector,与运行时初始化路径一致。

导出的 DDL 与运行时实现共享同一套表结构,例如 memory 域的messages表包含content CLOB NOT NULLrole VARCHAR2(64)等 Oracle 专属类型选择(见 schema.ts);vector 注册表插入使用MERGE INTO,保证 DDL 可重复执行而不产生重复注册行。


七、本地测试:Docker 启动 Oracle 23ai

仓库自带 docker-compose.yaml,用于集成测试与本地开发:

export ORACLE_DATABASE_USER=mastra export ORACLE_DATABASE_PASSWORD=yourpassword docker compose up -d --wait # 如需使用 HNSW 向量索引,重启一次使 Vector Pool 生效: docker compose restart db

容器使用gvenzl/oracle-free:23-slim-faststart,通过环境变量注入用户/密码,并把 scripts/configure-vector-memory.sql 挂载到初始化目录以持久化VECTOR_MEMORY_SIZE

需要注意:VECTOR_MEMORY_SIZE只有在数据库重启后才生效。不重启的情况下,Vector Pool 为 0:精确检索(默认)与 IVF 索引仍可工作,只有 HNSW 索引构建需要这一步(docker-compose 注释明确说明)。

包脚本(见 package.json):

  • pnpm test:unit:单元测试(vitest,排除集成测试);
  • pnpm test:integration:先docker compose up -d --wait,再分别运行存储与向量集成测试,最后docker compose down -v清理;
  • pnpm typecheck/pnpm lint:类型检查与 ESLint。

八、与 Mastra 生态的集成方式

8.1 与 Agent 内存集成

OracleStore通过getStore('memory')返回内存域,可与 Mastra 的Memory组合使用:

import { Memory } from '@mastra/memory'; const memory = new Memory({ storage: store }); await memory.init();

8.2 共享连接池模式

当存储与向量需要共享连接池时,注入同一个OraclePoolManager

import { OraclePoolManager } from '@mastra/oracledb'; const poolManager = new OraclePoolManager({ user: process.env.ORACLE_DATABASE_USER, password: process.env.ORACLE_DATABASE_PASSWORD, connectString: process.env.ORACLE_DATABASE_CONNECT_STRING, poolMax: 10, }); const store = new OracleStore({ id: 'oracle-store', poolManager }); const vector = new OracleVector({ id: 'oracle-vector', poolManager }); // 应用退出时统一释放 await store.close(); await vector.close();

8.3 与 RAG 集成

OracleVector继承 Mastra 的MastraVector基类,实现了upsert/query/deleteVector等标准向量接口,可无缝替换默认向量库,用于文档嵌入、语义检索、Memory 的语义召回等 RAG 场景。


九、总结

@mastra/oracledb将 Oracle Database 的能力完整桥接进 Mastra 生态:

  • 存储侧OracleStore覆盖 7 个存储域,自动迁移、批处理写入、CLOB/JSON 正确编码,可直接作为 Mastra Memory、工作流、可观测性、评估与 Agent 注册的持久化后端;
  • 向量侧OracleVector基于 Oracle 23ai 原生VECTOR类型,支持 HNSW/IVF 近似索引与精确检索、多种度量与向量格式、完整的 JSON 元数据过滤语法,并提供索引状态与精度诊断工具;
  • 工程化:共享连接池、幂等迁移、离线 DDL 导出、Docker 一键测试环境,兼顾了开发效率与生产可维护性。

如果你的团队已经运行 Oracle 数据库,@mastra/oracledb提供了一条无需引入额外基础设施即可获得 AI 存储与向量检索能力的路径。

延伸阅读

  • 包文档与版本历史:CHANGELOG.md
  • 连接池与连接配置实现:src/shared/connection.ts
  • 存储域实现:src/storage/
  • 向量实现:src/vector/
  • Schema 导出:src/schema.ts
  • 本地开发环境:docker-compose.yaml、scripts/configure-vector-memory.sql </output文章>

【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra

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

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

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

立即咨询