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

Redis中KNN向量相似度搜索无返回结果问题求助

排查思路与解决方案

核心问题定位:索引Schema与数据存储类型不匹配

你的Schema里用了$.text、$.embedding这类JSON路径表达式,但实际是通过HSET把数据存在Redis哈希(Hash)结构中,这会导致索引完全无法匹配到存储的哈希字段,直接造成搜索无结果。


逐条排查与修复步骤

1. 修正索引Schema与存储结构的匹配性

如果继续用哈希存储,需要把Schema里的JSON路径改成哈希字段名,去掉$.前缀:

const schema: RediSearchSchema = {
  'text': { // 去掉$.,直接对应哈希字段名
    type: SchemaFieldTypes.TEXT,
    AS: 'text',
  },
  'embedding': { // 同样去掉$.
    type: SchemaFieldTypes.VECTOR,
    ALGORITHM: VectorAlgorithms.HNSW,
    TYPE: 'FLOAT32',
    DIM: 1536,
    DISTANCE_METRIC: 'COSINE',
    AS: 'embedding',
  },
};

如果要改用JSON存储(匹配原Schema的JSON路径写法),则需要把HSET替换为JSON.SET:

// 改用JSON结构存储
await RedisClient.client.json.set(key, '$', {
  text: e.text,
  embedding: e.vector // 直接存数组,RedisJSON会自动处理,无需转Buffer
});

同时创建索引时要把ON: 'HASH'改成ON: 'JSON'。

2. 修复索引创建的异步问题

你的createIndices方法用了forEach+async/await,这会导致循环不等待每个索引创建完成,甚至出现索引未创建成功就开始存数据的情况,改成for...of循环:

private static async createIndices() {
  for (const i of RedisClient.indices) {
    try {
      await RedisClient.client.ft.CREATE(i.name, i.schema, {
        ON: 'HASH', // 对应哈希存储,用JSON则改为'JSON'
        PREFIX: i.prefix,
      });
    } catch (err) {
      // 仅忽略"索引已存在"的错误,其他错误抛出排查
      if ((err as Error).message.includes('Index already exists')) {
        console.log(`index ${i.name} already exists`);
      } else {
        throw err;
      }
    }
  }
}

3. 验证索引与数据的匹配性

  • 用Redis CLI执行FT.INFO contexts查看索引状态,确认num_docs是否为10(你的测试数据量),如果是0说明索引未匹配到数据。
  • 检查存储的key前缀是否和索引的PREFIX完全一致,比如KNOWLEGE_KEYS_PREFIX是否为'knowledge:',而你存储的key是否是'knowledge:1'这类格式,前缀必须完全匹配。
  • 用HGETALL <key>查看哈希字段,确认text和embedding字段存在,且embedding的Buffer长度为1536*4=6144字节(Float32每个元素占4字节,1536维总长度)。

4. 调整搜索参数细节

  • 确保搜索用的queryVector和存储的向量格式一致:同样通过Buffer.from(new Float32Array(queryVectorArray).buffer)转换。
  • 可以先去掉SORTBY简化查询测试,若vec_score字段不存在(索引未匹配到数据时会出现),排序会导致无结果:
const result = await RedisClient.client.ft.search(indexName, query, {
  PARAMS: {
    queryVector: queryVector,
  },
  DIALECT: 2,
  RETURN: ['text', 'vec_score'],
  LIMIT: {
    from: 0,
    size: top,
  },
});

验证步骤

  1. 删除旧索引:FT.DROPINDEX contexts
  2. 重启服务,确保索引创建成功
  3. 重新插入测试数据
  4. 用Redis CLI执行搜索命令验证:
FT.SEARCH contexts "*=>[KNN 5 @embedding $vec AS vec_score]" PARAMS 2 vec "<你的向量Buffer>" DIALECT 2 RETURN 2 text vec_score

如果CLI能搜到结果,说明代码逻辑没问题,再排查代码中的参数传递问题。

内容的提问来源于stack exchange,提问作者ZeroGravity

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:45:14