cloudflare-vectorize

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cloudflare Vectorize

Cloudflare Vectorize

Complete implementation guide for Cloudflare Vectorize - a globally distributed vector database for building semantic search, RAG (Retrieval Augmented Generation), and AI-powered applications with Cloudflare Workers.
Status: Production Ready ✅ Last Updated: 2026-01-21 Dependencies: cloudflare-worker-base (for Worker setup), cloudflare-workers-ai (for embeddings) Latest Versions: wrangler@4.59.3, @cloudflare/workers-types@4.20260109.0 Token Savings: ~70% Errors Prevented: 14 Dev Time Saved: ~4 hours
完整的Cloudflare Vectorize实现指南——这是一个全球分布式向量数据库,可用于在Cloudflare Workers上构建语义搜索、RAG(检索增强生成)和AI驱动的应用。
状态:已就绪可用于生产 ✅ 最后更新:2026-01-21 依赖项:cloudflare-worker-base(用于Worker设置)、cloudflare-workers-ai(用于生成嵌入向量) 最新版本:wrangler@4.59.3, @cloudflare/workers-types@4.20260109.0 Token节省率:约70% 预防的错误数量:14 节省的开发时间:约4小时

What This Skill Provides

本技能提供的内容

Core Capabilities

核心功能

  • Index Management: Create, configure, and manage vector indexes
  • Vector Operations: Insert, upsert, query, delete, and list vectors (list-vectors added August 2025)
  • Metadata Filtering: Advanced filtering with 10 metadata indexes per index
  • Semantic Search: Find similar vectors using cosine, euclidean, or dot-product metrics
  • RAG Patterns: Complete retrieval-augmented generation workflows
  • Workers AI Integration: Native embedding generation with @cf/baai/bge-base-en-v1.5
  • OpenAI Integration: Support for text-embedding-3-small/large models
  • Document Processing: Text chunking and batch ingestion pipelines
  • Testing Setup: Vitest configuration with Vectorize bindings
  • 索引管理:创建、配置和管理向量索引
  • 向量操作:插入、更新插入、查询、删除和列出向量(list-vectors功能于2025年8月新增)
  • 元数据过滤:每个索引支持10个元数据索引的高级过滤
  • 语义搜索:使用余弦、欧几里得或点积度量查找相似向量
  • RAG模式:完整的检索增强生成工作流
  • Workers AI集成:与@cf/baai/bge-base-en-v1.5原生集成生成嵌入向量
  • OpenAI集成:支持text-embedding-3-small/large模型
  • 文档处理:文本分块和批量摄入流水线
  • 测试设置:带有Vectorize绑定的Vitest配置

Templates Included

包含的模板

  1. basic-search.ts - Simple vector search with Workers AI
  2. rag-chat.ts - Full RAG chatbot with context retrieval
  3. document-ingestion.ts - Document chunking and embedding pipeline
  4. metadata-filtering.ts - Advanced filtering patterns

  1. basic-search.ts - 基于Workers AI的简单向量搜索
  2. rag-chat.ts - 带上下文检索的完整RAG聊天机器人
  3. document-ingestion.ts - 文档分块和嵌入向量流水线
  4. metadata-filtering.ts - 高级过滤模式

⚠️ Vectorize V2 Breaking Changes (September 2024)

⚠️ Vectorize V2重大变更(2024年9月)

IMPORTANT: Vectorize V2 became GA in September 2024 with significant breaking changes.
重要提示:Vectorize V2于2024年9月正式发布(GA),包含多项重大破坏性变更。

What Changed in V2

V2中的变更

Performance Improvements:
  • Index capacity: 200,000 → 5 million vectors per index
  • Query latency: 549ms → 31ms median (18× faster)
  • TopK limit: 20 → 100 results per query
  • Scale limits: 100 → 50,000 indexes per account
  • Namespace limits: 100 → 50,000 namespaces per index
Breaking API Changes:
  1. Async Mutations - All mutations now asynchronous:
    typescript
    // V2: Returns mutationId
    const result = await env.VECTORIZE_INDEX.insert(vectors);
    console.log(result.mutationId); // "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    
    // Vector inserts/deletes may take a few seconds to be reflected
  2. returnMetadata Parameter - Boolean → String enum:
    typescript
    // ❌ V1 (deprecated)
    { returnMetadata: true }
    
    // ✅ V2 (required)
    { returnMetadata: 'all' | 'indexed' | 'none' }
  3. Metadata Indexes Required Before Insert:
    • V2 requires metadata indexes created BEFORE vectors inserted
    • Vectors added before metadata index won't be indexed
    • Must re-upsert vectors after creating metadata index
V1 Deprecation Timeline:
  • December 2024: Can no longer create V1 indexes
  • Existing V1 indexes: Continue to work (other operations unaffected)
  • Migration: Use
    wrangler vectorize --deprecated-v1
    flag for V1 operations
Wrangler Version Required:
  • Minimum: wrangler@3.71.0 for V2 commands
  • Recommended: wrangler@4.54.0+ (latest)
性能提升
  • 索引容量:从20万 → 每个索引500万向量
  • 查询延迟:从549ms → 中位数31ms(快18倍)
  • TopK限制:从20 → 每次查询最多100个结果
  • 规模限制:从100 → 每个账户最多50,000个索引
  • 命名空间限制:从100 → 每个索引最多50,000个命名空间
破坏性API变更
  1. 异步变更 - 所有变更操作现在都是异步的:
    typescript
    // V2:返回mutationId
    const result = await env.VECTORIZE_INDEX.insert(vectors);
    console.log(result.mutationId); // "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    
    // 向量插入/删除可能需要几秒才会生效
  2. returnMetadata参数 - 从布尔值改为字符串枚举:
    typescript
    // ❌ V1(已弃用)
    { returnMetadata: true }
    
    // ✅ V2(必填)
    { returnMetadata: 'all' | 'indexed' | 'none' }
  3. 插入向量前必须创建元数据索引
    • V2要求在插入向量前先创建元数据索引
    • 在元数据索引创建前添加的向量无法被索引
    • 创建元数据索引后必须重新插入或更新插入向量
V1弃用时间线
  • 2024年12月:无法再创建V1索引
  • 现有V1索引:可继续使用(其他操作不受影响)
  • 迁移:使用
    wrangler vectorize --deprecated-v1
    标志执行V1操作
所需Wrangler版本
  • 最低版本:wrangler@3.71.0(用于V2命令)
  • 推荐版本:wrangler@4.54.0+(最新版)

Check Mutation Status

检查变更状态

typescript
// Get index info to check last mutation processed
const info = await env.VECTORIZE_INDEX.describe();
console.log(info.mutationId); // Last mutation ID
console.log(info.processedUpToMutation); // Last processed timestamp

typescript
// 获取索引信息以检查最后处理的变更
const info = await env.VECTORIZE_INDEX.describe();
console.log(info.mutationId); // 最后一个变更ID
console.log(info.processedUpToMutation); // 最后处理的时间戳

Critical Setup Rules

关键设置规则

⚠️ MUST DO BEFORE INSERTING VECTORS

⚠️ 插入向量前必须完成的操作

bash
undefined
bash
undefined

1. Create the index with FIXED dimensions and metric

1. 创建具有固定维度和度量的索引

npx wrangler vectorize create my-index
--dimensions=768
--metric=cosine
npx wrangler vectorize create my-index
--dimensions=768
--metric=cosine

2. Create metadata indexes IMMEDIATELY (before inserting vectors!)

2. 立即创建元数据索引(在插入向量之前!)

npx wrangler vectorize create-metadata-index my-index
--property-name=category
--type=string
npx wrangler vectorize create-metadata-index my-index
--property-name=timestamp
--type=number

**Why**: Metadata indexes MUST exist before vectors are inserted. Vectors added before a metadata index was created won't be filterable on that property.
npx wrangler vectorize create-metadata-index my-index
--property-name=category
--type=string
npx wrangler vectorize create-metadata-index my-index
--property-name=timestamp
--type=number

**原因**:元数据索引必须在插入向量前存在。在元数据索引创建前添加的向量无法通过该属性进行过滤。

Index Configuration (Cannot Be Changed Later)

索引配置(创建后无法修改)

bash
undefined
bash
undefined

Dimensions MUST match your embedding model output:

维度必须与嵌入向量模型的输出匹配:

- Workers AI @cf/baai/bge-base-en-v1.5: 768 dimensions

- Workers AI @cf/baai/bge-base-en-v1.5:768维度

- OpenAI text-embedding-3-small: 1536 dimensions

- OpenAI text-embedding-3-small:1536维度

- OpenAI text-embedding-3-large: 3072 dimensions

- OpenAI text-embedding-3-large:3072维度

Metrics determine similarity calculation:

度量方式决定相似度计算:

- cosine: Best for normalized embeddings (most common)

- cosine:最适合归一化嵌入向量(最常用)

- euclidean: Absolute distance between vectors

- euclidean:向量间的绝对距离

- dot-product: For non-normalized vectors

- dot-product:用于非归一化向量

undefined
undefined

Wrangler Configuration

Wrangler配置

wrangler.jsonc:
jsonc
{
  "name": "my-vectorize-worker",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-21",
  "vectorize": [
    {
      "binding": "VECTORIZE_INDEX",
      "index_name": "my-index"
    }
  ],
  "ai": {
    "binding": "AI"
  }
}
wrangler.jsonc
jsonc
{
  "name": "my-vectorize-worker",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-21",
  "vectorize": [
    {
      "binding": "VECTORIZE_INDEX",
      "index_name": "my-index"
    }
  ],
  "ai": {
    "binding": "AI"
  }
}

TypeScript Types

TypeScript类型

typescript
export interface Env {
  VECTORIZE_INDEX: VectorizeIndex;
  AI: Ai;
}

interface VectorizeVector {
  id: string;
  values: number[] | Float32Array | Float64Array;
  namespace?: string;
  metadata?: Record<string, string | number | boolean | string[]>;
}

interface VectorizeMatches {
  matches: Array<{
    id: string;
    score: number;
    values?: number[];
    metadata?: Record<string, any>;
    namespace?: string;
  }>;
  count: number;
}
typescript
export interface Env {
  VECTORIZE_INDEX: VectorizeIndex;
  AI: Ai;
}

interface VectorizeVector {
  id: string;
  values: number[] | Float32Array | Float64Array;
  namespace?: string;
  metadata?: Record<string, string | number | boolean | string[]>;
}

interface VectorizeMatches {
  matches: Array<{
    id: string;
    score: number;
    values?: number[];
    metadata?: Record<string, any>;
    namespace?: string;
  }>;
  count: number;
}

Metadata Filter Operators (V2)

元数据过滤操作符(V2)

Vectorize V2 supports advanced metadata filtering with range queries:
typescript
// Equality (implicit $eq)
{ category: "docs" }

// Not equals
{ status: { $ne: "archived" } }

// In/Not in arrays
{ category: { $in: ["docs", "tutorials"] } }
{ category: { $nin: ["deprecated", "draft"] } }

// Range queries (numbers) - NEW in V2
{ timestamp: { $gte: 1704067200, $lt: 1735689600 } }

// Range queries (strings) - prefix searching
{ url: { $gte: "/docs/workers", $lt: "/docs/workersz" } }

// Nested metadata with dot notation
{ "author.id": "user123" }

// Multiple conditions (implicit AND)
{ category: "docs", language: "en", "metadata.published": true }
Vectorize V2支持带范围查询的高级元数据过滤:
typescript
// 相等(隐式$eq)
{ category: "docs" }

// 不等于
{ status: { $ne: "archived" } }

// 在/不在数组中
{ category: { $in: ["docs", "tutorials"] } }
{ category: { $nin: ["deprecated", "draft"] } }

// 范围查询(数字)- V2新增
{ timestamp: { $gte: 1704067200, $lt: 1735689600 } }

// 范围查询(字符串)- 前缀搜索
{ url: { $gte: "/docs/workers", $lt: "/docs/workersz" } }

// 使用点符号的嵌套元数据
{ "author.id": "user123" }

// 多条件(隐式AND)
{ category: "docs", language: "en", "metadata.published": true }

Metadata Best Practices

元数据最佳实践

1. Cardinality Considerations

1. 基数考量

Low Cardinality (Good for $eq filters):
typescript
// Few unique values - efficient filtering
metadata: {
  category: "docs",        // ~10 categories
  language: "en",          // ~5 languages
  published: true          // 2 values (boolean)
}
High Cardinality (Avoid in range queries):
typescript
// Many unique values - avoid large range scans
metadata: {
  user_id: "uuid-v4...",         // Millions of unique values
  timestamp_ms: 1704067200123    // Use seconds instead
}
低基数(适合$eq过滤)
typescript
// 唯一值少 - 过滤效率高
metadata: {
  category: "docs",        // 约10个分类
  language: "en",          // 约5种语言
  published: true          // 2个值(布尔型)
}
高基数(避免用于范围查询)
typescript
// 唯一值多 - 避免大范围扫描
metadata: {
  user_id: "uuid-v4...",         // 数百万个唯一值
  timestamp_ms: 1704067200123    // 改用秒级时间戳
}

2. Metadata Limits

2. 元数据限制

  • Max 10 metadata indexes per Vectorize index
  • Max 10 KiB metadata per vector
  • String indexes: First 64 bytes (UTF-8)
  • Number indexes: Float64 precision
  • Filter size: Max 2048 bytes (compact JSON)
  • 每个Vectorize索引最多10个元数据索引
  • 每个向量的元数据最大10 KiB
  • 字符串索引:前64字节(UTF-8)
  • 数字索引:Float64精度
  • 过滤条件大小:最大2048字节(压缩JSON)

3. Vector Dimension Limit

3. 向量维度限制

Current Limit: 1536 dimensions per vector Source: GitHub Issue #8729
Supported Embedding Models:
  • Workers AI
    @cf/baai/bge-base-en-v1.5
    : 768 dimensions ✅
  • OpenAI
    text-embedding-3-small
    : 1536 dimensions ✅
  • OpenAI
    text-embedding-3-large
    : 3072 dimensions ❌ (requires dimension reduction)
Unsupported Models (>1536 dimensions):
  • nomic-embed-code
    : 3584 dimensions
  • Qodo-Embed-1-7B
    : >1536 dimensions
Workaround: Use dimensionality reduction (e.g., PCA) to compress embeddings to 1536 or fewer dimensions, though this may reduce semantic quality.
Feature Request: Higher dimension support is under consideration. Use Limit Increase Request Form if this blocks your use case.
当前限制:每个向量最多1536维度 来源GitHub Issue #8729
支持的嵌入向量模型
  • Workers AI
    @cf/baai/bge-base-en-v1.5
    :768维度 ✅
  • OpenAI
    text-embedding-3-small
    :1536维度 ✅
  • OpenAI
    text-embedding-3-large
    :3072维度 ❌(需要降维)
不支持的模型(>1536维度):
  • nomic-embed-code
    :3584维度
  • Qodo-Embed-1-7B
    :>1536维度
解决方法: 使用降维方法(如PCA)将嵌入向量压缩到1536或更少维度,但这可能会降低语义质量。
功能请求:正在考虑支持更高维度。如果此限制阻碍了你的使用,请使用限制提升请求表单

4. Key Restrictions

4. 关键限制

typescript
// ❌ INVALID metadata keys
metadata: {
  "": "value",              // Empty key
  "user.name": "John",      // Contains dot (reserved for nesting)
  "$admin": true,           // Starts with $
  "key\"with\"quotes": 1    // Contains quotes
}

// ✅ VALID metadata keys
metadata: {
  "user_name": "John",
  "isAdmin": true,
  "nested": { "allowed": true }  // Access as "nested.allowed" in filters
}
typescript
// ❌ 无效的元数据键
metadata: {
  "": "value",              // 空键
  "user.name": "John",      // 包含点(保留用于嵌套)
  "$admin": true,           // 以$开头
  "key\"with\"quotes": 1    // 包含引号
}

// ✅ 有效的元数据键
metadata: {
  "user_name": "John",
  "isAdmin": true,
  "nested": { "allowed": true }  // 在过滤中以"nested.allowed"访问
}

Best Practices

最佳实践

Batch Insert Performance

批量插入性能

Critical: Use batch size of 5000 vectors for optimal performance.
Performance Data:
  • Individual inserts: 2.5M vectors in 36+ hours (incomplete)
  • Batch inserts (5000): 4M vectors in ~12 hours
  • 18× faster with proper batching
Why 5000?
  • Vectorize's internal Write-Ahead Log (WAL) optimized for this size
  • Avoids Cloudflare API rate limits
  • Balances throughput and memory usage
Optimal Pattern:
typescript
const BATCH_SIZE = 5000;

async function insertVectors(vectors: VectorizeVector[]) {
  for (let i = 0; i < vectors.length; i += BATCH_SIZE) {
    const batch = vectors.slice(i, i + BATCH_SIZE);
    const result = await env.VECTORIZE.insert(batch);
    console.log(`Inserted batch ${i / BATCH_SIZE + 1}, mutationId: ${result.mutationId}`);

    // Optional: Rate limiting delay
    if (i + BATCH_SIZE < vectors.length) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  }
}
Sources:

关键:使用5000个向量的批量大小以获得最佳性能。
性能数据
  • 单次插入:36小时以上插入250万向量(未完成)
  • 批量插入(5000):约12小时插入400万向量
  • 使用正确的批量大小快18倍
为什么是5000?
  • Vectorize的内部预写日志(WAL)针对此大小优化
  • 避免Cloudflare API速率限制
  • 平衡吞吐量和内存使用
最优模式
typescript
const BATCH_SIZE = 5000;

async function insertVectors(vectors: VectorizeVector[]) {
  for (let i = 0; i < vectors.length; i += BATCH_SIZE) {
    const batch = vectors.slice(i, i + BATCH_SIZE);
    const result = await env.VECTORIZE.insert(batch);
    console.log(`插入批次 ${i / BATCH_SIZE + 1},mutationId: ${result.mutationId}`);

    // 可选:速率限制延迟
    if (i + BATCH_SIZE < vectors.length) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  }
}
来源

Query Accuracy Modes

查询精度模式

Vectorize uses approximate nearest neighbor (ANN) search by default with ~80% accuracy compared to exact search.
Default Mode: Approximate scoring (~80% accuracy)
  • Faster latency
  • Good for RAG, search, recommendations
  • topK up to 100
High-Precision Mode: Near 100% accuracy
  • Enabled via
    returnValues: true
  • Higher latency
  • Limited to topK=20
Trade-off Example:
typescript
// Fast, ~80% accuracy, topK up to 100
const results = await env.VECTORIZE.query(embedding, {
  topK: 50,
  returnValues: false  // Default
});

// Slower, ~100% accuracy, topK max 20
const preciseResults = await env.VECTORIZE.query(embedding, {
  topK: 10,
  returnValues: true   // High-precision scoring
});
When to Use High-Precision:
  • Critical applications (fraud detection, legal compliance)
  • Small result sets (topK < 20)
  • Accuracy is higher priority than latency

Vectorize默认使用近似最近邻(ANN)搜索,与精确搜索相比精度约为80%。
默认模式:近似评分(约80%精度)
  • 延迟更低
  • 适合RAG、搜索、推荐
  • topK最多100
高精度模式:接近100%精度
  • 通过
    returnValues: true
    启用
  • 延迟更高
  • 限制topK=20
权衡示例
typescript
// 快速,约80%精度,topK最多100
const results = await env.VECTORIZE.query(embedding, {
  topK: 50,
  returnValues: false  // 默认
});

// 较慢,约100%精度,topK最大20
const preciseResults = await env.VECTORIZE.query(embedding, {
  topK: 10,
  returnValues: true   // 高精度评分
});
何时使用高精度模式
  • 关键应用(欺诈检测、合规性)
  • 小结果集(topK < 20)
  • 精度优先于延迟

Common Errors & Solutions

常见错误与解决方案

Error 1: Metadata Index Created After Vectors Inserted

错误1:元数据索引在插入向量后创建

Problem: Filtering doesn't work on existing vectors
Solution: Delete and re-insert vectors OR create metadata indexes BEFORE inserting
问题:现有向量无法被过滤
解决方案:删除并重新插入向量 或 在插入向量前创建元数据索引

Error 2: Dimension Mismatch

错误2:维度不匹配

Problem: "Vector dimensions do not match index configuration"
Solution: Ensure embedding model output matches index dimensions:
  - Workers AI bge-base: 768
  - OpenAI small: 1536
  - OpenAI large: 3072
问题:"Vector dimensions do not match index configuration"
解决方案:确保嵌入向量模型的输出与索引维度匹配:
  - Workers AI bge-base: 768
  - OpenAI small: 1536
  - OpenAI large: 3072

Error 3: Invalid Metadata Keys

错误3:无效的元数据键

Problem: "Invalid metadata key"
Solution: Keys cannot:
  - Be empty
  - Contain . (dot)
  - Contain " (quote)
  - Start with $ (dollar sign)
问题:"Invalid metadata key"
解决方案:键不能:
  - 为空
  - 包含.(点)
  - 包含"(引号)
  - 以$(美元符号)开头

Error 4: Filter Too Large

错误4:过滤条件过大

Problem: "Filter exceeds 2048 bytes"
Solution: Simplify filter or split into multiple queries
问题:"Filter exceeds 2048 bytes"
解决方案:简化过滤条件或拆分为多个查询

Error 5: Range Query on High Cardinality

错误5:高基数字段的范围查询

Problem: Slow queries or reduced accuracy
Solution: Use lower cardinality fields for range queries, or use seconds instead of milliseconds for timestamps
问题:查询缓慢或精度降低
解决方案:使用低基数字段进行范围查询,或对时间戳使用秒级而非毫秒级

Error 6: Insert vs Upsert Confusion

错误6:Insert与Upsert混淆

Problem: Updates not reflecting in index
Solution: Use upsert() to overwrite existing vectors, not insert()
问题:更新未在索引中生效
解决方案:使用upsert()覆盖现有向量,而非insert()

Error 7: Missing Bindings

错误7:缺少绑定

Problem: "VECTORIZE_INDEX is not defined"
Solution: Add [[vectorize]] binding to wrangler.jsonc
问题:"VECTORIZE_INDEX is not defined"
解决方案:在wrangler.jsonc中添加[[vectorize]]绑定

Error 8: Namespace vs Metadata Confusion

错误8:命名空间与元数据混淆

Problem: Unclear when to use namespace vs metadata filtering
Solution:
  - Namespace: Partition key, applied BEFORE metadata filters
  - Metadata: Flexible key-value filtering within namespace
问题:不清楚何时使用命名空间 vs 元数据过滤
解决方案:
  - 命名空间:分区键,在元数据过滤前应用
  - 元数据:命名空间内灵活的键值对过滤

Error 9: V2 Async Mutation Timing (NEW in V2)

错误9:V2异步变更时序(V2新增)

Problem: Inserted vectors not immediately queryable
Solution: V2 mutations are asynchronous - vectors may take a few seconds to be reflected
  - Use mutationId to track mutation status
  - Check env.VECTORIZE_INDEX.describe() for processedUpToMutation timestamp
问题:插入的向量无法立即查询到
解决方案:V2变更是异步的 - 向量可能需要几秒才会生效
  - 使用mutationId跟踪变更状态
  - 检查env.VECTORIZE_INDEX.describe()的processedUpToMutation时间戳

Error 10: V1 returnMetadata Boolean (BREAKING in V2)

错误10:V1的returnMetadata布尔值(V2中已破坏)

Problem: "returnMetadata must be 'all', 'indexed', or 'none'"
Solution: V2 changed returnMetadata from boolean to string enum:
  - ❌ V1: { returnMetadata: true }
  - ✅ V2: { returnMetadata: 'all' }
问题:"returnMetadata must be 'all', 'indexed', or 'none'"
解决方案:V2将returnMetadata从布尔值改为字符串枚举:
  - ❌ V1: { returnMetadata: true }
  - ✅ V2: { returnMetadata: 'all' }

Error 11: Wrangler --json Output Contains Log Prefix

错误11:Wrangler --json输出包含日志前缀

Error:
wrangler vectorize list --json
output starts with log message, breaking JSON parsing Source: GitHub Issue #11011
Affected Commands:
  • wrangler vectorize list --json
  • wrangler vectorize list-metadata-index --json
Problem:
bash
$ wrangler vectorize list --json
📋 Listing Vectorize indexes...
[
  { "created_on": "2025-10-18T13:28:30.259277Z", ... }
]
The log message makes output invalid JSON, breaking piping to
jq
or other tools.
Solution: Strip first line before parsing:
bash
undefined
错误
wrangler vectorize list --json
输出以日志消息开头,导致JSON解析失败 来源GitHub Issue #11011
受影响的命令
  • wrangler vectorize list --json
  • wrangler vectorize list-metadata-index --json
问题
bash
$ wrangler vectorize list --json
📋 Listing Vectorize indexes...
[
  { "created_on": "2025-10-18T13:28:30.259277Z", ... }
]
日志消息导致输出为无效JSON,无法通过
jq
等工具处理。
解决方案:解析前删除第一行:
bash
undefined

Using tail

使用tail

wrangler vectorize list --json | tail -n +2 | jq '.'
wrangler vectorize list --json | tail -n +2 | jq '.'

Using sed

使用sed

wrangler vectorize list --json | sed '1d' | jq '.'

---
wrangler vectorize list --json | sed '1d' | jq '.'

---

Error 12: TypeScript Types Missing Filter Operators

错误12:TypeScript类型缺少过滤操作符

Error:
wrangler types
generates incomplete
VectorizeVectorMetadataFilterOp
type Source: GitHub Issue #10092 Status: OPEN (tracked internally as VS-461)
Problem: Generated type only includes
$eq
and
$ne
, missing V2 operators:
$in
,
$nin
,
$lt
,
$lte
,
$gt
,
$gte
Impact: TypeScript shows false errors when using valid V2 metadata filter operators:
typescript
const vectorizeRes = env.VECTORIZE.queryById(imgId, {
  filter: { gender: { $in: genderFilters } }, // ❌ TS error but works!
  topK,
  returnMetadata: 'indexed',
});
Workaround: Manual type override until wrangler types is fixed:
typescript
// Add to your types file
type VectorizeMetadataFilter = Record<string,
  | string
  | number
  | boolean
  | {
      $eq?: string | number | boolean;
      $ne?: string | number | boolean;
      $in?: (string | number | boolean)[];
      $nin?: (string | number | boolean)[];
      $lt?: number | string;
      $lte?: number | string;
      $gt?: number | string;
      $gte?: number | string;
    }
>;

错误
wrangler types
生成的
VectorizeVectorMetadataFilterOp
类型不完整 来源GitHub Issue #10092 状态:OPEN(内部跟踪编号VS-461)
问题: 生成的类型仅包含
$eq
$ne
,缺少V2操作符:
$in
,
$nin
,
$lt
,
$lte
,
$gt
,
$gte
影响: 使用有效的V2元数据过滤操作符时,TypeScript会显示错误,但实际运行正常:
typescript
const vectorizeRes = env.VECTORIZE.queryById(imgId, {
  filter: { gender: { $in: genderFilters } }, // ❌ TS错误但可正常运行!
  topK,
  returnMetadata: 'indexed',
});
解决方法:在wrangler types修复前手动覆盖类型:
typescript
// 添加到你的类型文件
type VectorizeMetadataFilter = Record<string,
  | string
  | number
  | boolean
  | {
      $eq?: string | number | boolean;
      $ne?: string | number | boolean;
      $in?: (string | number | boolean)[];
      $nin?: (string | number | boolean)[];
      $lt?: number | string;
      $lte?: number | string;
      $gt?: number | string;
      $gte?: number | string;
    }
>;

Error 13: Windows Dev Registry Failure (FIXED)

错误13:Windows开发环境注册表失败(已修复)

Error:
ENOENT: no such file or directory
when running
wrangler dev
on Windows Source: GitHub Issue #10383 Status: FIXED in wrangler@4.32.0
Problem: Wrangler attempted to create external worker files with colons in the name (invalid on Windows):
Error: ENOENT: ... '__WRANGLER_EXTERNAL_VECTORIZE_WORKER:<project>:<binding>'
Solution: Update to wrangler@4.32.0 or later:
bash
npm install -g wrangler@latest

错误:在Windows上运行
wrangler dev
时出现
ENOENT: no such file or directory
来源GitHub Issue #10383 状态:在wrangler@4.32.0中已修复
问题: Wrangler尝试创建名称包含冒号的外部Worker文件(Windows不支持):
Error: ENOENT: ... '__WRANGLER_EXTERNAL_VECTORIZE_WORKER:<project>:<binding>'
解决方案: 更新到wrangler@4.32.0或更高版本:
bash
npm install -g wrangler@latest

Error 14: topK Limit Depends on returnValues/returnMetadata

错误14:topK限制取决于returnValues/returnMetadata

Error:
topK exceeds maximum allowed value
Source: Vectorize Limits
Problem: Maximum topK value changes based on query options:
ConfigurationMax topK
returnValues: false
,
returnMetadata: 'none'
100
returnValues: true
OR
returnMetadata: 'all'
20
returnMetadata: 'indexed'
100
Common Error:
typescript
// ❌ ERROR - topK too high with returnValues
query(embedding, {
  topK: 100,            // Exceeds limit!
  returnValues: true    // Max topK=20 when true
});
Solution:
typescript
// ✅ OK - respects conditional limit
query(embedding, {
  topK: 20,
  returnValues: true
});

// ✅ OK - higher topK without values
query(embedding, {
  topK: 100,
  returnValues: false,
  returnMetadata: 'indexed'
});

错误
topK exceeds maximum allowed value
来源Vectorize限制
问题:最大topK值根据查询选项变化:
配置最大topK
returnValues: false
,
returnMetadata: 'none'
100
returnValues: true
returnMetadata: 'all'
20
returnMetadata: 'indexed'
100
常见错误
typescript
// ❌ 错误 - returnValues为true时topK过高
query(embedding, {
  topK: 100,            // 超过限制!
  returnValues: true    // 当为true时最大topK=20
});
解决方案
typescript
// ✅ 正确 - 遵守条件限制
query(embedding, {
  topK: 20,
  returnValues: true
});

// ✅ 正确 - 不返回值时使用更高的topK
query(embedding, {
  topK: 100,
  returnValues: false,
  returnMetadata: 'indexed'
});

V2 Migration Checklist

V2迁移检查清单

If migrating from V1 to V2:
  1. ✅ Update wrangler to 3.71.0+ (
    npm install -g wrangler@latest
    )
  2. ✅ Create new V2 index (can't upgrade V1 → V2)
  3. ✅ Create metadata indexes BEFORE inserting vectors
  4. ✅ Update
    returnMetadata
    boolean → string enum ('all', 'indexed', 'none')
  5. ✅ Handle async mutations (expect
    mutationId
    in responses)
  6. ✅ Test with V2 limits (topK up to 100, 5M vectors per index)
  7. ✅ Update error handling for async behavior
V1 Deprecation:
  • After December 2024: Cannot create new V1 indexes
  • Existing V1 indexes: Continue to work
  • Use
    wrangler vectorize --deprecated-v1
    for V1 operations

如果从V1迁移到V2
  1. ✅ 将wrangler更新到3.71.0+(
    npm install -g wrangler@latest
  2. ✅ 创建新的V2索引(无法将V1升级到V2)
  3. ✅ 在插入向量前创建元数据索引
  4. ✅ 将
    returnMetadata
    从布尔值改为字符串枚举('all', 'indexed', 'none')
  5. ✅ 处理异步变更(响应中包含
    mutationId
  6. ✅ 测试V2限制(topK最多100,每个索引500万向量)
  7. ✅ 更新针对异步行为的错误处理
V1弃用
  • 2024年12月后:无法创建新的V1索引
  • 现有V1索引:可继续使用
  • 执行V1操作使用
    wrangler vectorize --deprecated-v1

Testing Considerations

测试注意事项

Vitest with Vectorize Bindings

使用Vectorize绑定的Vitest

Issue: Using
@cloudflare/vitest-pool-workers
with Vectorize or Workers AI bindings causes runtime failure. Source: GitHub Issue #7434
Error:
wrapped binding module can't be resolved
Workaround:
  1. Create
    wrangler-test.jsonc
    without Vectorize/AI bindings
  2. Point vitest config to test-specific wrangler file
  3. Mock bindings in your tests
Example:
typescript
// wrangler-test.jsonc (no Vectorize binding)
{
  "name": "my-worker-test",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-21"
  // No vectorize binding
}

// vitest.config.ts
import { defineWorkersProject } from '@cloudflare/vitest-pool-workers/config';

export default defineWorkersProject({
  test: {
    poolOptions: {
      workers: {
        wrangler: {
          configPath: "./wrangler-test.jsonc"
        }
      }
    }
  }
});

// Mock in tests
import { vi } from 'vitest';

const mockVectorize = {
  query: vi.fn().mockResolvedValue({
    matches: [
      { id: 'test-1', score: 0.95, metadata: { category: 'docs' } }
    ],
    count: 1
  }),
  insert: vi.fn().mockResolvedValue({ mutationId: "test-mutation-id" }),
  upsert: vi.fn().mockResolvedValue({ mutationId: "test-mutation-id" })
};

// Use mock in tests
test('vector search', async () => {
  const env = { VECTORIZE_INDEX: mockVectorize };
  // ... test logic
});

问题:使用
@cloudflare/vitest-pool-workers
搭配Vectorize或Workers AI绑定会导致运行时失败。 来源GitHub Issue #7434
错误
wrapped binding module can't be resolved
解决方法
  1. 创建不带Vectorize/AI绑定的
    wrangler-test.jsonc
  2. 将vitest配置指向测试专用的wrangler文件
  3. 在测试中模拟绑定
示例
typescript
// wrangler-test.jsonc(无Vectorize绑定)
{
  "name": "my-worker-test",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-21"
  // 无vectorize绑定
}

// vitest.config.ts
import { defineWorkersProject } from '@cloudflare/vitest-pool-workers/config';

export default defineWorkersProject({
  test: {
    poolOptions: {
      workers: {
        wrangler: {
          configPath: "./wrangler-test.jsonc"
        }
      }
    }
  }
});

// 在测试中模拟
import { vi } from 'vitest';

const mockVectorize = {
  query: vi.fn().mockResolvedValue({
    matches: [
      { id: 'test-1', score: 0.95, metadata: { category: 'docs' } }
    ],
    count: 1
  }),
  insert: vi.fn().mockResolvedValue({ mutationId: "test-mutation-id" }),
  upsert: vi.fn().mockResolvedValue({ mutationId: "test-mutation-id" })
};

// 在测试中使用模拟
test('vector search', async () => {
  const env = { VECTORIZE_INDEX: mockVectorize };
  // ... 测试逻辑
});

Community Tips

社区技巧

Note: These tips come from community discussions and official blog posts. Verify against your Vectorize version.
注意:这些技巧来自社区讨论和官方博客。请根据你的Vectorize版本进行验证。

Tip 1: Range Queries at Scale May Have Reduced Accuracy (Community-sourced)

技巧1:大规模范围查询可能降低精度(社区贡献)

Source: Query Best Practices Confidence: MEDIUM Applies to: Datasets with ~10M+ vectors
Range queries (
$lt
,
$lte
,
$gt
,
$gte
) on large datasets may experience reduced accuracy.
Optimization Strategy:
typescript
// ❌ High-cardinality range at scale
metadata: {
  timestamp_ms: 1704067200123
}
filter: { timestamp_ms: { $gte: 1704067200000 } }

// ✅ Bucketed into discrete values
metadata: {
  timestamp_bucket: "2025-01-01-00:00",  // 1-hour buckets
  timestamp_ms: 1704067200123  // Original (non-indexed)
}
filter: {
  timestamp_bucket: {
    $in: ["2025-01-01-00:00", "2025-01-01-01:00"]
  }
}
When This Matters:
  • Time-based filtering over months/years
  • User IDs, transaction IDs (UUID ranges)
  • Any high-cardinality continuous data
Alternative: Use equality filters (
$eq
,
$in
) with bucketed values.

来源查询最佳实践 可信度:中等 适用场景:数据集约1000万+向量
在大型数据集上使用范围查询(
$lt
,
$lte
,
$gt
,
$gte
)可能会降低精度。
优化策略
typescript
// ❌ 大规模高基数范围查询
metadata: {
  timestamp_ms: 1704067200123
}
filter: { timestamp_ms: { $gte: 1704067200000 } }

// ✅ 分桶为离散值
metadata: {
  timestamp_bucket: "2025-01-01-00:00",  // 1小时分桶
  timestamp_ms: 1704067200123  // 原始值(未索引)
}
filter: {
  timestamp_bucket: {
    $in: ["2025-01-01-00:00", "2025-01-01-01:00"]
  }
}
适用场景
  • 基于时间的跨月/年过滤
  • 用户ID、交易ID(UUID范围)
  • 任何高基数连续数据
替代方案:使用等值过滤(
$eq
,
$in
)搭配分桶后的值。

Tip 2: List Vectors Operation (Added August 2025)

技巧2:列出向量操作(2025年8月新增)

Vectorize V2 added support for the
list-vectors
operation for paginated iteration through vector IDs.
Use Cases:
  • Auditing vector collections
  • Bulk vector operations
  • Debugging index contents
API:
typescript
const result = await env.VECTORIZE_INDEX.list({
  limit: 1000,  // Max 1000 per page
  cursor?: string
});

// result.vectors: Array<{ id: string }>
// result.cursor: string | undefined
// result.count: number

// Pagination example
let cursor: string | undefined;
const allVectorIds: string[] = [];

do {
  const result = await env.VECTORIZE_INDEX.list({
    limit: 1000,
    cursor
  });
  allVectorIds.push(...result.vectors.map(v => v.id));
  cursor = result.cursor;
} while (cursor);
Limitations:
  • Returns IDs only (not values or metadata)
  • Max 1000 vectors per page
  • Use cursor for pagination

Vectorize V2新增了
list-vectors
操作,支持分页遍历向量ID。
使用场景
  • 审计向量集合
  • 批量向量操作
  • 调试索引内容
API
typescript
const result = await env.VECTORIZE_INDEX.list({
  limit: 1000,  // 每页最多1000个
  cursor?: string
});

// result.vectors: Array<{ id: string }>
// result.cursor: string | undefined
// result.count: number

// 分页示例
let cursor: string | undefined;
const allVectorIds: string[] = [];

do {
  const result = await env.VECTORIZE_INDEX.list({
    limit: 1000,
    cursor
  });
  allVectorIds.push(...result.vectors.map(v => v.id));
  cursor = result.cursor;
} while (cursor);
限制
  • 仅返回ID(不返回值或元数据)
  • 每页最多1000个向量
  • 使用cursor进行分页

Official Documentation

官方文档


Status: Production Ready ✅ (Vectorize V2 GA - September 2024) Last Updated: 2026-01-21 Token Savings: ~70% Errors Prevented: 14 (includes V2 breaking changes, testing setup, TypeScript types) Changes: Added 4 new errors (wrangler --json, TypeScript types, Windows dev, topK limits), batch performance best practices, query accuracy modes, testing setup, community tips on range queries and list-vectors operation.

状态:已就绪可用于生产 ✅(Vectorize V2 GA - 2024年9月) 最后更新:2026-01-21 Token节省率:约70% 预防的错误数量:14(包括V2破坏性变更、测试设置、TypeScript类型问题) 变更:新增4类错误(wrangler --json、TypeScript类型、Windows开发、topK限制)、批量性能最佳实践、查询精度模式、测试设置、关于范围查询和list-vectors操作的社区技巧。