FT.SEARCH

语法
FT.SEARCH index query 
  [NOCONTENT] 
  [VERBATIM] [NOSTOPWORDS] 
  [WITHSCORES] 
  [WITHPAYLOADS] 
  [WITHSORTKEYS] 
  [FILTER numeric_field min max [ FILTER numeric_field min max ...]] 
  [GEOFILTER geo_field lon lat radius m | km | mi | ft [ GEOFILTER geo_field lon lat radius m | km | mi | ft ...]] 
  [INKEYS count key [key ...]] [ INFIELDS count field [field ...]] 
  [RETURN count identifier [AS property] [ identifier [AS property] ...]] 
  [SUMMARIZE [ FIELDS count field [field ...]] [FRAGS num] [LEN fragsize] [SEPARATOR separator]] 
  [HIGHLIGHT [ FIELDS count field [field ...]] [ TAGS open close]] 
  [SLOP slop] 
  [TIMEOUT timeout] 
  [INORDER] 
  [LANGUAGE language] 
  [EXPANDER expander] 
  [SCORER scorer] 
  [EXPLAINSCORE] 
  [PAYLOAD payload] 
  [SORTBY sortby [ ASC | DESC] [WITHCOUNT]] 
  [LIMIT offset num] 
  [PARAMS nargs name value [ name value ...]] 
  [DIALECT dialect]
可用
Redis Stack / Search 1.0.0
时间复杂度
O(N)

使用文本查询搜索索引,返回文档或仅返回 ID。

示例

必需参数

索引

是索引名称。您必须先使用 FT.CREATE 创建索引。

查询

是要搜索的文本查询。如果查询包含多个单词,请将查询放在引号中。有关更多详细信息,请参阅 查询语法

可选参数

NOCONTENT

返回文档 ID,而不是内容。如果 RediSearch 只是对外部文档集合的索引,这将很有用。

VERBATIM

不会尝试使用词干提取进行查询扩展,而是按原样搜索查询词。

WITHSCORES

还返回每个文档的相对内部分数。这可用于合并来自多个实例的结果。

WITHPAYLOADS

检索可选的文档有效负载。请参阅 FT.CREATE。有效负载位于文档 ID 之后,如果设置了 WITHSCORES,则位于分数之后。

WITHSORTKEYS

返回排序键的值,位于 ID、分数和/或有效负载之后(如果已请求)。这通常不需要,并且存在于分布式搜索协调目的。此选项仅在与 SORTBY 结合使用时才相关。

FILTER numeric_attribute min max

将结果限制为那些具有介于 minmax 之间的数值的那些,如果 numeric_attribute 在 FT.CREATE 中定义为数值属性。minmax 遵循 ZRANGE 语法,并且可以是 -inf+inf,并且使用 ( 表示排他性范围。一个查询支持对不同属性使用多个数字过滤器。自 v2.10 起已弃用查询方言 2 解释了用于替代此参数的数字字段的查询语法。

GEOFILTER {geo_attribute} {lon} {lat} {radius} m|km|mi|ft

将结果过滤为距 lonlat 指定 radius 的那些。半径以数字和单位给出。有关更多详细信息,请参阅 GEORADIUS自 v2.6 起已弃用查询方言 3 解释了用于替代此参数的地理空间字段的查询语法。

INKEYS {num} {attribute} ...

将结果限制为列表中指定的一组键。第一个参数必须是列表的长度,并且大于零。除非所有键都不存在,否则将忽略不存在的键。

INFIELDS {num} {attribute} ...

将结果过滤为那些仅出现在文档的特定属性中,例如 titleURL。您必须包含 num,它是您要过滤的属性数量。例如,如果您请求 titleURL,则 num 为 2。

RETURN {num} {identifier} AS {property} ...

限制从文档返回的属性。num 是关键字后面的属性数量。如果 num 为 0,它将像 NOCONTENT 一样工作。identifier 是属性名称(对于哈希和 JSON)或 JSON 路径表达式(对于 JSON)。property 是结果中使用的可选名称。如果未提供,则结果中将使用 identifier

SUMMARIZE ...

仅返回包含匹配文本的属性部分。有关更多信息,请参阅 突出显示

HIGHLIGHT ...

格式化匹配文本的出现次数。有关更多信息,请参阅 突出显示

SLOP {slop}

是在查询词之间允许出现的中间词的数量。假设您正在搜索短语 hello world。如果 helloworld 之间出现一些词,则大于 0SLOP 允许这些文本属性匹配。默认情况下,没有 SLOP 约束。

INORDER

要求文档中的词语与查询中的词语具有相同的顺序,而不管它们之间的偏移量如何。通常与 SLOP 结合使用。默认值为 false

LANGUAGE {language}

在搜索查询扩展期间,使用针对提供语言的词干提取器。如果查询中文文档,则设置为chinese以正确分词查询词语。默认值为英文。如果发送了不支持的语言,则命令将返回错误。有关语言列表,请参见FT.CREATE。如果在索引创建过程中指定了LANGUAGE,则无需在FT.SEARCH中指定。

EXPANDER {expander}

使用自定义查询扩展器而不是词干提取器。请参见扩展

SCORER {scorer}

使用内置用户提供的评分函数。

EXPLAINSCORE

返回关于如何计算分数的文本描述。使用此选项需要WITHSCORES

PAYLOAD {payload}

添加一个任意的、二进制安全的有效负载,该有效负载将公开给自定义评分函数。请参见扩展

SORTBY {attribute} [ASC|DESC] [WITHCOUNT]

按此属性的值对结果进行排序。这适用于文本和数值属性。为了能够以非常低的延迟使用SORTBY,需要在索引中将所需的属性声明为SORTABLE。请注意,这会增加内存开销。

排序优化:在不同的场景下,针对DIALECT 4中的排序操作进行了性能优化

  • 跳过排序器 - 当没有进行任何排序时适用。查询可以在达到请求结果的LIMIT后返回。
  • 部分范围 - 当存在对数值字段的SORTBY子句时适用,并且没有过滤器或按相同数值字段进行过滤,查询将在足够大的范围内迭代以满足请求结果的LIMIT
  • 混合 - 当存在对数值字段的SORTBY子句以及其他非数值过滤器时适用。一些结果将被过滤,初始范围可能不够大。然后,迭代器将使用以下范围进行回绕,并进行额外的迭代以收集请求结果的LIMIT
  • 无优化 - 如果按分数或按非数值字段排序,则别无选择,只能检索所有结果并比较它们的值。

计数行为:可选的WITHCOUNT参数返回查询结果的准确计数,并进行排序。此操作将处理所有结果以获得准确的计数,其性能低于优化选项(DIALECT 4上的默认行为)

LIMIT first num

将结果限制为给定的偏移量和结果数量。请注意,偏移量从零开始。默认值为 0 10,它从第一个结果开始返回 10 个项目。您可以使用LIMIT 0 0来计算结果集中的文档数量,而不实际返回它们。

TIMEOUT {milliseconds}

覆盖模块的超时参数。

PARAMS {nargs} {name} {value}

定义一个或多个值参数。每个参数都有一个名称和一个值。

您可以在query中通过一个$,后跟参数名称来引用参数,例如,$user。搜索查询中对参数名称的每个此类引用都将被相应的参数值替换。例如,使用参数定义PARAMS 4 lon 29.69465 lat 34.95126,表达式@loc:[$lon $lat 10 km]将被评估为@loc:[29.69465 34.95126 10 km]。您不能在查询字符串中引用参数,在该字符串中不允许使用具体值,例如在字段名称中,例如,@loc。要使用PARAMS,请将DIALECT设置为2或大于2(这需要RediSearch v2.4或更高版本)。

DIALECT {dialect_version}

选择要在其下执行查询的方言版本。如果未指定,则查询将在模块初始加载期间设置的默认方言版本或通过FT.CONFIG SET命令设置的默认方言版本下执行。有关更多信息,请参见查询方言

返回值

FT.SEARCH 返回一个数组回复,其中第一个元素是结果总数的整数回复,然后是文档 ID 的数组回复对,以及属性/值对的数组回复。

说明
  • 如果给定了NOCONTENT,则返回一个数组,其中第一个元素是结果总数,其余成员是文档 ID。
  • 如果在查询运行时相关键过期,则尝试加载键的值将返回一个空数组。但是,该键仍在结果总数中进行计数。

返回多个值

当索引定义为ON JSON时,当 JSONPath 匹配多个值或 JSONPath 匹配数组时,单个属性或单个 JSONPath 的回复可能会返回多个值。

在 RediSearch v2.6 之前,只返回第一个匹配的值。从 RediSearch v2.6 开始,将返回所有值,并用顶层数组进行包装。

为了保持向后兼容性,RediSearch v2.6 的默认行为是只返回第一个值。

要返回所有值,请使用DIALECT 3(或更高版本,如果可用)。

DIALECT 可以作为参数在 FT.SEARCH 命令中指定。如果未指定,则使用DEFAULT_DIALECT,它可以使用FT.CONFIG SET设置,也可以在加载redisearch模块时将其作为参数传递。

例如,使用以下文档和索引

127.0.0.1:6379> JSON.SET doc:1 $ '[{"arr": [1, 2, 3]}, {"val": "hello"}, {"val": "world"}]'
OK
127.0.0.1:6379> FT.CREATE idx ON JSON PREFIX 1 doc: SCHEMA $..arr AS arr NUMERIC $..val AS val TEXT
OK

注意,使用和不使用DIALECT 3时,回复有所不同

127.0.0.1:6379> FT.SEARCH idx * RETURN 2 arr val
1) (integer) 1
2) "doc:1"
3) 1) "arr"
   2) "[1,2,3]"
   3) "val"
   4) "hello"

127.0.0.1:6379> FT.SEARCH idx * RETURN 2 arr val DIALECT 3
1) (integer) 1
2) "doc:1"
3) 1) "arr"
   2) "[[1,2,3]]"
   3) "val"
   4) "[\"hello\",\"world\"]"

复杂度

对于单个词查询,FT.SEARCH 的复杂度为 O(n)。n 是结果集中结果的数量。查找包含特定词语的所有文档的复杂度为 O(1),但是,需要对所有这些文档进行扫描才能从 Redis 哈希加载文档数据并返回它们。

更复杂查询的时间复杂度有所不同,但通常与词语数量、它们之间的交点数量以及结果集中结果的数量成正比。

示例

在每个文本属性中搜索词语

在包含书籍数据的索引的每个 TEXT 属性中搜索词语“wizard”。

127.0.0.1:6379> FT.SEARCH books-idx "wizard"
在标题属性中搜索词语

title属性中搜索词语dogs

127.0.0.1:6379> FT.SEARCH books-idx "@title:dogs"
搜索特定年份的书籍

搜索在 2020 年或 2021 年出版的书籍。

127.0.0.1:6379> FT.SEARCH books-idx "@published_at:[2020 2021]"
按距离从经度/纬度搜索餐厅

搜索距离经度 -122.41、纬度 37.77(旧金山) 5 公里范围内的中餐馆。

127.0.0.1:6379> FT.SEARCH restaurants-idx "chinese @location:[-122.41 37.77 5 km]"
按词语搜索书籍,但提升特定词语的权重

title属性中搜索词语dogscats,但给与dogs匹配更高的相关性分数(也称为提升)。

127.0.0.1:6379> FT.SEARCH books-idx "(@title:dogs | @title:cats) | (@title:dogs) => { $weight: 5.0; }"
按词语搜索书籍并 EXPLAINSCORE

在索引的任何 TEXT 属性中搜索包含dogs的书籍,并请求对每个结果的评分进行说明。

127.0.0.1:6379> FT.SEARCH books-idx "dogs" WITHSCORES EXPLAINSCORE
按词语和 TAG 搜索书籍

搜索标题中包含space并且在 TAG 属性categories中包含science的书籍。

127.0.0.1:6379> FT.SEARCH books-idx "@title:space @categories:{science}"
按词语搜索书籍,但限制数量

搜索在任何TEXT属性中包含Python的书籍,返回 10 个结果,从整个结果集中的第 11 个结果开始(偏移量参数从零开始),并且只返回每个结果的title属性。

127.0.0.1:6379> FT.SEARCH books-idx "python" LIMIT 10 10 RETURN 1 title
按词语和价格搜索书籍

搜索在任何TEXT属性中包含Python的书籍,返回存储在原始 JSON 文档中的价格。

127.0.0.1:6379> FT.SEARCH books-idx "python" RETURN 3 $.book.price AS price
按标题和距离搜索书籍

搜索标题与Planet Earth在语义上相似的书籍。按距离返回前 10 个结果。

127.0.0.1:6379> FT.SEARCH books-idx "*=>[KNN 10 @title_embedding $query_vec AS title_score]" PARAMS 2 query_vec <"Planet Earth" embedding BLOB> SORTBY title_score DIALECT 2
使用 SLOP 搜索短语

搜索短语hello world。首先,创建一个索引。

127.0.0.1:6379> FT.CREATE memes SCHEMA phrase TEXT
OK

添加短语hello world的不同变体。

127.0.0.1:6379> HSET s1 phrase "hello world"
(integer) 1
127.0.0.1:6379> HSET s2 phrase "hello simple world"
(integer) 1
127.0.0.1:6379> HSET s3 phrase "hello somewhat less simple world"
(integer) 1
127.0.0.1:6379> HSET s4 phrase "hello complicated yet encouraging problem solving world"
(integer) 1
127.0.0.1:6379> HSET s5 phrase "hello complicated yet amazingly encouraging problem solving world"
(integer) 1

然后,搜索短语hello world。结果将返回所有包含该短语的文档。

127.0.0.1:6379> FT.SEARCH memes '@phrase:(hello world)' NOCONTENT 
1) (integer) 5
2) "s1"
3) "s2"
4) "s3"
5) "s4"
6) "s5"

现在,返回所有helloworld之间有一个或更少词语的文档。

127.0.0.1:6379> FT.SEARCH memes '@phrase:(hello world)' NOCONTENT SLOP 1
1) (integer) 2
2) "s1"
3) "s2"

现在,返回所有helloworld之间有三个或更少词语的文档。

127.0.0.1:6379> FT.SEARCH memes '@phrase:(hello world)' NOCONTENT SLOP 3
1) (integer) 3
2) "s1"
3) "s2"
4) "s3"

s5需要更高的SLOP才能匹配,SLOP 6或更高,才能精确匹配。看看将SLOP设置为5会发生什么。

127.0.0.1:6379> FT.SEARCH memes '@phrase:(hello world)' NOCONTENT SLOP 5
1) (integer) 4
2) "s1"
3) "s2"
4) "s3"
5) "s4"

如果你添加了额外的词语(和词干提取),你会得到这些结果。

127.0.0.1:6379> FT.SEARCH memes '@phrase:(hello amazing world)' NOCONTENT 
1) (integer) 1
2) "s5"
127.0.0.1:6379> FT.SEARCH memes '@phrase:(hello encouraged world)' NOCONTENT SLOP 5
1) (integer) 2
2) "s4"
3) "s5"
127.0.0.1:6379> FT.SEARCH memes '@phrase:(hello encouraged world)' NOCONTENT SLOP 4
1) (integer) 1
2) "s4"

如果你交换了词语,你仍然可以检索到正确的短语。

127.0.0.1:6379> FT.SEARCH memes '@phrase:(amazing hello world)' NOCONTENT
1) (integer) 1
2) "s5"

但是,如果你使用INORDER,你将得到零个结果。

127.0.0.1:6379> FT.SEARCH memes '@phrase:(amazing hello world)' NOCONTENT INORDER
1) (integer) 0

同样,如果你使用设置为true的查询属性$inorder,则不会检索到s5

127.0.0.1:6379> FT.SEARCH memes '@phrase:(amazing hello world)=>{$inorder: true;}' NOCONTENT
1) (integer) 0

总而言之,INORDER参数或$inorder查询属性要求查询词语与排序类似的词语匹配。

使用 WITHIN、CONTAINS、INTERSECTS 和 DISJOINT 运算符进行多边形搜索

查询多边形,这些多边形

  • 包含给定的地理形状
  • 位于给定的地理形状内
  • 与给定的地理形状相交
  • 与给定的形状分离(没有共同点)

首先,使用GEOSHAPE类型和FLAT坐标系创建一个索引

127.0.0.1:6379> FT.CREATE idx SCHEMA geom GEOSHAPE FLAT
OK

使用HSET添加几个几何图形

127.0.0.1:6379> HSET small geom 'POLYGON((1 1, 1 100, 100 100, 100 1, 1 1))'
(integer) 1
127.0.0.1:6379> HSET large geom 'POLYGON((1 1, 1 200, 200 200, 200 1, 1 1))'
(integer) 1

使用WITHIN运算符查询

127.0.0.1:6379> FT.SEARCH idx '@geom:[WITHIN $poly]' PARAMS 2 poly 'POLYGON((0 0, 0 150, 150 150, 150 0, 0 0))' DIALECT 3

1) (integer) 1
2) "small"
3) 1) "geom"
   2) "POLYGON((1 1, 1 100, 100 100, 100 1, 1 1))"

使用CONTAINS运算符查询

127.0.0.1:6379> FT.SEARCH idx '@geom:[CONTAINS $poly]' PARAMS 2 poly 'POLYGON((2 2, 2 50, 50 50, 50 2, 2 2))' DIALECT 3

1) (integer) 2
2) "small"
3) 1) "geom"
   2) "POLYGON((1 1, 1 100, 100 100, 100 1, 1 1))"
4) "large"
5) 1) "geom"
   2) "POLYGON((1 1, 1 200, 200 200, 200 1, 1 1))"

另请参见

FT.CREATE | FT.AGGREGATE


历史

  • 从 Redis 版本 2.0.0 开始:弃用WITHPAYLOADSPAYLOAD参数
  • 从 Redis 版本 2.6 开始:弃用GEOFILTER参数
  • 从 Redis 版本 2.10 开始:弃用FILTER参数
RATE THIS PAGE
Back to top ↑