跳到主要内容

Convex Vector 存储

ConvexVector 类使用 Convex 提供 Vector 存储和相似度搜索。它将 embedding 存储在 Convex 中,并在 Mastra adapter 中执行余弦相似度搜索。

适用于开发规模的搜索

ConvexVector 通过 Mastra storage handler 读取匹配的 Vector,在 JavaScript 中进行过滤,计算余弦相似度,对结果排序,并返回最匹配的结果。它适用于本地开发、测试和小型数据集。

对于 Convex 上的生产环境 Vector 搜索,请使用 ConvexNativeVector。它使用 Convex 原生 vectorSearch API,因而需要已部署的 Convex Vector 索引和 Convex action。

安装
安装的直接链接

npm install @mastra/convex@latest

Convex 设置
Convex 设置的直接链接

使用 ConvexVector 前,需要设置 Convex schema 和 storage handler。设置说明请参阅 Convex Storage 设置

构造函数选项
构造函数选项的直接链接

deploymentUrl:

string
Convex 部署 URL(例如 https://your-project.convex.cloud)

adminAuthToken:

string
Convex 管理员身份验证 token

storageFunction?:

string
= mastra/storage:handle
storage mutation 函数的路径

构造函数示例
构造函数示例的直接链接

基本配置
基本配置的直接链接

import { ConvexVector } from '@mastra/convex'

const vectorStore = new ConvexVector({
id: 'convex-vectors',
deploymentUrl: 'https://your-project.convex.cloud',
adminAuthToken: 'your-admin-token',
})

对于生产环境 Vector 工作负载,请使用 ConvexNativeVector。它将 Vector 存储在专用的 Convex 表中,并查询在 schema 中定义的 Convex Vector 索引。

convex/schema.ts 中,为每个 Mastra Vector 索引定义一个专用表:

convex/schema.ts
import { defineSchema } from 'convex/server'
import { defineMastraNativeVectorTable } from '@mastra/convex/schema'

export default defineSchema({
docs_vectors: defineMastraNativeVectorTable({
dimensions: 1536,
}),
})

convex/mastra/nativeVector.ts 中,导出原生 Vector handler:

convex/mastra/nativeVector.ts
import {
mastraNativeVectorAction,
mastraNativeVectorMutation,
mastraNativeVectorQuery,
} from '@mastra/convex/server'

export const query = mastraNativeVectorAction
export const read = mastraNativeVectorQuery
export const write = mastraNativeVectorMutation

在 Mastra 应用中,使用已部署的表和 Vector 索引配置 ConvexNativeVector

src/mastra/index.ts
import { ConvexNativeVector } from '@mastra/convex'

const vectorStore = new ConvexNativeVector({
id: 'convex-native-vectors',
deploymentUrl: process.env.CONVEX_URL!,
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
indexes: {
docs: {
tableName: 'docs_vectors',
vectorIndexName: 'by_embedding',
dimension: 1536,
},
},
})

const results = await vectorStore.query({
indexName: 'docs',
queryVector: embedding,
topK: 10,
})

如需原生过滤支持,请在 Convex schema 中声明过滤字段。写入 Vector 时,原生 Vector handler 会将匹配的元数据字段复制到顶层文档字段。

convex/schema.ts
import { defineSchema, defineTable } from 'convex/server'
import { v } from 'convex/values'

export default defineSchema({
docs_vectors: defineTable({
id: v.string(),
embedding: v.array(v.float64()),
metadata: v.optional(v.any()),
tenantId: v.string(),
})
.index('by_record_id', ['id'])
.vectorIndex('by_embedding', {
vectorField: 'embedding',
dimensions: 1536,
filterFields: ['tenantId'],
}),
})
src/mastra/index.ts
const vectorStore = new ConvexNativeVector({
id: 'convex-native-vectors',
deploymentUrl: process.env.CONVEX_URL!,
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
indexes: {
docs: {
tableName: 'docs_vectors',
dimension: 1536,
filterFields: ['tenantId'],
},
},
})

await vectorStore.upsert({
indexName: 'docs',
ids: ['chunk-1'],
vectors: [embedding],
metadata: [{ tenantId: 'acme', text: 'Account setup guide' }],
})

const results = await vectorStore.query({
indexName: 'docs',
queryVector: embedding,
filter: { tenantId: 'acme' },
})

ConvexNativeVector 支持 Convex 原生 Vector 过滤结构:一个等值字段,或由多个等值字段组成的 $or。它不支持仅元数据查询、基于过滤条件的更新或基于过滤条件的删除。更新和删除时请使用 Vector ID。

自定义 storage 函数
自定义 storage 函数的直接链接

const vectorStore = new ConvexVector({
id: 'convex-vectors',
deploymentUrl: 'https://your-project.convex.cloud',
adminAuthToken: 'your-admin-token',
storageFunction: 'custom/path:handler',
})

方法
方法的直接链接

createIndex()
createindex的直接链接

indexName:

string
要创建的索引名称

dimension:

number
Vector 维度(必须与 embedding 模型匹配)

metric?:

'cosine' | 'euclidean' | 'dotproduct'
= cosine
相似度搜索的距离度量(目前仅支持 cosine)
await vectorStore.createIndex({
indexName: 'my_vectors',
dimension: 1536,
})

upsert()
upsert的直接链接

indexName:

string
要执行 Vector upsert 的索引名称

vectors:

number[][]
embedding Vector 数组

metadata?:

Record<string, any>[]
每个 Vector 的元数据

ids?:

string[]
可选的 Vector ID(未提供时自动生成)
await vectorStore.upsert({
indexName: "my_vectors",
vectors: [[0.1, 0.2, 0.3, ...]],
metadata: [{ label: "example" }],
ids: ["vec-1"],
});

query()
query的直接链接

indexName:

string
要查询的索引名称

queryVector:

number[]
查询 Vector

topK?:

number
= 10
要返回的结果数量

filter?:

Record<string, any>
元数据过滤条件

includeVector?:

boolean
= false
是否在结果中包含 Vector
const results = await vectorStore.query({
indexName: "my_vectors",
queryVector: [0.1, 0.2, 0.3, ...],
topK: 5,
filter: { category: "documents" },
});

listIndexes()
listindexes的直接链接

返回由索引名称字符串组成的数组。

const indexes = await vectorStore.listIndexes()
// ["my_vectors", "embeddings", ...]

describeIndex()
describeindex的直接链接

indexName:

string
要描述的索引名称

返回:

interface IndexStats {
dimension: number
count: number
metric: 'cosine' | 'euclidean' | 'dotproduct'
}

deleteIndex()
deleteindex的直接链接

indexName:

string
要删除的索引名称

删除索引及其中的所有 Vector。

await vectorStore.deleteIndex({ indexName: 'my_vectors' })

updateVector()
updatevector的直接链接

通过 ID 或元数据过滤条件更新单个 Vector。必须提供 idfilter,但不能同时提供二者。

indexName:

string
包含该 Vector 的索引名称

id?:

string
要更新的 Vector ID(与 filter 互斥)

filter?:

Record<string, any>
用于识别要更新 Vector 的元数据过滤条件(与 id 互斥)

update:

{ vector?: number[]; metadata?: Record<string, any>; }
包含要更新的 Vector 和/或元数据的对象
// Update by ID
await vectorStore.updateVector({
indexName: 'my_vectors',
id: 'vector123',
update: {
vector: [0.1, 0.2, 0.3],
metadata: { label: 'updated' },
},
})

// Update by filter
await vectorStore.updateVector({
indexName: 'my_vectors',
filter: { category: 'product' },
update: {
metadata: { status: 'reviewed' },
},
})

deleteVector()
deletevector的直接链接

indexName:

string
包含该 Vector 的索引名称

id:

string
要删除的 Vector ID
await vectorStore.deleteVector({ indexName: 'my_vectors', id: 'vector123' })

deleteVectors()
deletevectors的直接链接

通过 ID 或元数据过滤条件删除多个 Vector。必须提供 idsfilter,但不能同时提供二者。

indexName:

string
包含要删除 Vector 的索引名称

ids?:

string[]
要删除的 Vector ID 数组(与 filter 互斥)

filter?:

Record<string, any>
用于识别要删除 Vector 的元数据过滤条件(与 ids 互斥)
// Delete by IDs
await vectorStore.deleteVectors({
indexName: 'my_vectors',
ids: ['vec1', 'vec2', 'vec3'],
})

// Delete by filter
await vectorStore.deleteVectors({
indexName: 'my_vectors',
filter: { status: 'archived' },
})

响应类型
响应类型的直接链接

查询结果按以下格式返回:

interface QueryResult {
id: string
score: number
metadata: Record<string, any>
vector?: number[] // Only included if includeVector is true
}

元数据过滤
元数据过滤的直接链接

ConvexVector 支持使用运算符进行元数据过滤。这些过滤条件由 adapter 在从 Convex 加载 Vector 后应用。

// Simple equality
const results = await vectorStore.query({
indexName: 'my_vectors',
queryVector: embedding,
filter: { category: 'documents' },
})

// Comparison operators
const results = await vectorStore.query({
indexName: 'my_vectors',
queryVector: embedding,
filter: {
price: { $gt: 100 },
status: { $in: ['active', 'pending'] },
},
})

// Logical operators
const results = await vectorStore.query({
indexName: 'my_vectors',
queryVector: embedding,
filter: {
$and: [{ category: 'electronics' }, { price: { $lte: 500 } }],
},
})

支持的过滤运算符
支持的过滤运算符的直接链接

运算符描述
$eq等于
$ne不等于
$gt大于
$gte大于或等于
$lt小于
$lte小于或等于
$in在数组中
$nin不在数组中
$and逻辑 AND
$or逻辑 OR

架构
架构的直接链接

ConvexVector 将 Vector 存储在 mastra_vectors 表中,结构如下:

  • id:唯一的 Vector 标识符
  • indexName:索引名称
  • embedding:Vector 数据(浮点数数组)
  • metadata:可选的 JSON 元数据

Vector 相似度搜索通过 Mastra adapter 中的余弦相似度执行。这种方式让设置保持灵活,但不适合大型生产环境 Vector 集合。

ConvexNativeVector 将每个 Mastra Vector 索引存储在专用的 Convex 表中。其查询会调用使用 ctx.vectorSearch 的 Convex action,然后通过 Convex query 加载匹配的文档。这遵循 Convex 原生 Vector 搜索模型:

  • Vector 索引在 convex/schema.ts 中声明。
  • Vector 搜索从 Convex action 运行。
  • topK 必须介于 1256 之间。
  • 过滤条件必须以 Convex Vector 索引 filterFields 中列出的字段为目标。
  • 每个 Mastra Vector 索引使用一个专用表,以避免出现跨索引结果。

如果需要在运行时定义索引创建、仅元数据查询、复杂的过滤运算符、基于过滤条件的批量更新或删除,或者结果数量上限超过 Convex 原生 Vector 搜索的限制,请使用外部 Vector 数据库。