FT.SEARCH

FT.SEARCH 使用提供的查询搜索索引,并返回指定的值。请注意,FT.SEARCH 会返回整个集群的结果,而不仅仅是查询的节点的结果。

您还可以将 FT.SEARCH 用于 JSON 文档。如需启用此功能, 请对 JSON 数据使用 FT.CREATE 创建索引,然后指定要编入索引的字段。

如需详细了解查询语法,请参阅查询语法

语法

FT.SEARCH index query
  [NOCONTENT]
  [TIMEOUT timeout]
  [PARAMS nargs name value [ name value ...]]
  [RETURN num field [AS alias] [ field [AS alias] ... ]]
  [LIMIT offset num]
  DIALECT 2
  • index(必需):您要查询的索引。
  • query(必需):这是您的查询。如需详细了解查询语法,请参阅查询语法
  • NOCONTENT (可选):此选项仅返回文档 ID,不返回内容。
  • TIMEOUT(可选):此选项可让您为搜索命令设置超时值。
  • PARAMS(可选):键值对的数量乘以 2。
  • RETURN(可选):此选项用于指定要从文档中检索的字段,以及返回值的任何别名。默认情况下,除非设置了 NOCONTENT 选项,否则系统会返回所有字段;如果设置了该选项,则系统不会返回任何字段。如果将 num 设置为 0,则其行为与 NOCONTENT 相同。
  • LIMIT (可选):此选项可让您选择使用偏移量和数字计数进行分页。如果您不使用此参数,则默认值为 LIMIT 0 10,最多返回 10 个键。
  • DIALECT 2(可选):此选项用于指定方言。唯一受支持的方言是方言 2。

命令返回

  • 此命令会返回数组或错误消息。返回的数组的元素表示查询的最佳匹配结果。每个数组元素都具有以下内容:

  • 条目哈希键

  • 以下内容的数组:

    • 键值:[$score_as ] score_value
    • 距离值
    • 属性名称
    • 向量值

    如果使用 NOCONTENT,则数组元素仅包含文档 ID。

示例 1:简单向量搜索查询

在此示例中,假设我们要构建一个房产搜索索引,客户可以根据某些特征搜索房产。假设我们有一个房产列表,其中包含以下属性:

  • 说明 - 给定房产的向量嵌入。
  • 其他字段 - 每处房产还可以包含其他元数据。不过,为简单起见,在此示例中忽略了其他字段。

首先,我们使用 FT.CREATE 命令创建一个 HNSW 索引,并将说明作为向量字段:

FT.CREATE idx SCHEMA description VECTOR HNSW 6 TYPE FLOAT32 DIM 3 DISTANCE_METRIC L2

现在,我们可以使用 HSET 命令插入一些属性(也可以在创建索引之前执行此操作):

HSET p1 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"
HSET p2 description "\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00"
HSET p3 description "\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00"
HSET p4 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"
HSET p5 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"

现在,我们可以使用 FT.SEARCH 命令执行查询。以下查询最多返回五个与提供的查询向量最相似的房产:

FT.SEARCH idx "*=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2

返回的结果:

 1) (integer) 5
 2) p5
 3) 1) __description_score
    2) 1.6400001049
    3) description
    4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
 4) p4
 5) 1) __description_score
    2) 1.6400001049
    3) description
    4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
 6) p2
 7) 1) __description_score
    2) 1.6400001049
    3) description
    4) \x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00
 8) p1
 9) 1) __description_score
    2) 1.6400001049
    3) description
    4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
10) p3
11) 1) __description_score
    2) 0.0399999953806
    3) description
    4) \x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00

代码示例

Python

# Before running, ensure you have installed redis-py:
#    pip install redis

import redis
client = redis.cluster.RedisCluster(host='your_redis_host', port=6379)
result = client.execute_command('FT.SEARCH', 'idx', '*=>[KNN 5 @description $query_vector]', 'PARAMS', '2', 'query_vector', '"\xcd\xccL?\x00\x00\x00\x00"', 'DIALECT', '2')
print(result)

NodeJS

# Before running, ensure you have installed ioredis:
#   npm install ioredis

const Redis = require("ioredis");
const redis = new Redis.Cluster([
{
  port: 6379,
  host: "your_redis_host",
},
]);
redis.call("FT.SEARCH", "idx", "*=>[KNN 5 @description $query_vector]", "PARAMS", "2", "query_vector", "\xcd\xccL?\x00\x00\x00\x00\x00\x00", "DIALECT", "2").then(result => {
console.log(result);
redis.disconnect();
});

CLI

# Before running, ensure you have install redis-cli

redis-cli -h your_redis_host -p 6379 FT.SEARCH idx "(*)=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2

示例 2:使用混合查询的向量搜索

在此示例中,我们将使用另外两个名为 city 和 price 的属性执行 混合查询

  • 说明 - 给定房产的向量嵌入。
  • City - 城市名称。
  • Price - 房产的价格。

首先,我们创建一个索引,并将说明作为向量字段,将 city 作为标记字段,将 price 作为数字字段:

FT.CREATE idx SCHEMA description VECTOR HNSW 6 TYPE FLOAT32 DIM 3 DISTANCE_METRIC L2 city TAG price NUMERIC

现在,我们可以插入一些属性(也可以在创建索引之前执行此操作):

HSET p1 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?" city "NEW YORK" price 500000
HSET p2 description "\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00" city "NEW JERSEY" price 400000
HSET p3 description "\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00" city "BANGALORE" price 60000
HSET p4 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?" city "NEW YORK" price 600000
HSET p5 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?" city "BANGALORE" price 75000

现在,我们可以执行查询。以下查询最多返回五个与提供的查询向量最相似的房产,并且仅过滤到位于 BANGALORE 且价格低于 100000 的房产:

FT.SEARCH idx "(@city:{BANGALORE} @price:[-inf 100000])=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2

返回的结果:

1) (integer) 2
2) p5
3) 1) __description_score
   2) 1.6400001049
   3) city
   4) BANGALORE
   5) price
   6) 75000
   7) description
   8) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
4) p3
5) 1) __description_score
   2) 0.0399999953806
   3) city
   4) BANGALORE
   5) price
   6) 60000
   7) description
   8) \x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00

如需详细了解过滤条件查询格式,请参阅查询语法

代码示例

Python

# Before running, ensure you have installed redis-py:
#   pip install redis

import redis
client = redis.cluster.RedisCluster(host='your_redis_host', port=6379)
result = client.execute_command('FT.SEARCH', 'idx', '(@city:{BANGALORE} @price:[-inf 100000])=>[KNN 5 @description $query_vector]', 'PARAMS', '2', 'query_vector', '"\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00"', 'DIALECT', '2')
print(result)

NodeJS

# Before running, ensure you have installed ioredis:
#   npm install ioredis

const Redis = require("ioredis");
const redis = new Redis.Cluster([
{
  port: 6379,
  host: "your_redis_host",
},
]);
redis.call("FT.SEARCH", "idx", "(@city:{BANGALORE} @price:[-inf 100000])=>[KNN 5 @description $query_vector]", "PARAMS", "2", "query_vector", "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00", "DIALECT", "2").then(result => {
console.log(result);
redis.disconnect();
});

CLI

# Before running, ensure you have install redis-cli

redis-cli -h your_redis_host -p 6379 FT.SEARCH idx "(@city:{BANGALORE} @price:[-inf 100000])=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2