FT.SEARCH

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

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

语法

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 命令执行查询。以下查询最多会返回 5 个与所提供的查询向量最相似的房源:

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”的属性执行混合查询

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

首先,我们创建一个索引,其中将说明作为向量字段,将城市作为标记字段,将价格作为数值字段:

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

现在,我们可以执行查询了。以下查询会返回最多 5 个与所提供的查询向量最相似的房源,但仅限价格低于 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