FT.SEARCH

Syntax
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]
Available in:
Redis Stack / Search 1.0.0
Time complexity:
O(N)

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

示例

必需的参数

index

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

query

是用于搜索的文本查询。如果超过一个单词,请用引号括起来。有关更多详细信息,请参阅查询语法

可选参数

NOCONTENT

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

VERBATIM

不尝试使用词干提取进行查询扩展,而是逐字搜索查询词。

NOSTOPWORDS

忽略全文搜索中定义的任何停用词。

WITHSCORES

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

WITHPAYLOADS

检索可选的文档负载。参见FT.CREATE。负载跟随文档ID,如果设置了WITHSCORES,则跟随分数。

WITHSORTKEYS

返回排序键的值,紧接在id和score以及/或payload之后(如果请求了)。这通常不需要,并且是为了分布式搜索协调目的而存在的。此选项仅在与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,它的行为类似于 NOCONTENTidentifier 是属性名称(用于哈希和 JSON)或 JSON Path 表达式(用于 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来计算结果集中的文档数量,而无需实际返回它们。

LIMIT 行为: 如果你使用 LIMIT 选项而不进行排序,返回的结果是不确定的,这意味着后续查询可能会返回重复或缺失的值。添加带有唯一字段的 SORTBY,或使用带有 WITHCURSOR 选项的 FT.AGGREGATE 以确保确定性的结果集分页。

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的数组回复对,以及属性/值对的数组回复。

Notes:
  • 如果给出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 哈希中加载文档数据并返回它们。

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

示例

Search for a term in every text attribute

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

127.0.0.1:6379> FT.SEARCH books-idx "wizard"
Search for a term in title attribute

title属性中搜索术语dogs

127.0.0.1:6379> FT.SEARCH books-idx "@title:dogs"
Search for books from specific years

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

127.0.0.1:6379> FT.SEARCH books-idx "@published_at:[2020 2021]"
Search for a restaurant by distance from longitude/latitude

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

127.0.0.1:6379> FT.SEARCH restaurants-idx "chinese @location:[-122.41 37.77 5 km]"
Search for a book by terms but boost specific term

title属性中搜索术语dogscats,但给dogs的匹配项更高的相关性分数(也称为boosting)。

127.0.0.1:6379> FT.SEARCH books-idx "(@title:dogs | @title:cats) | (@title:dogs) => { $weight: 5.0; }"
Search for a book by a term and EXPLAINSCORE

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

127.0.0.1:6379> FT.SEARCH books-idx "dogs" WITHSCORES EXPLAINSCORE
Search for a book by a term and TAG

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

127.0.0.1:6379> FT.SEARCH books-idx "@title:space @categories:{science}"
Search for a book by a term but limit the number

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

127.0.0.1:6379> FT.SEARCH books-idx "python" LIMIT 10 10 RETURN 1 title
Search for a book by a term and price

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

127.0.0.1:6379> FT.SEARCH books-idx "python" RETURN 3 $.book.price AS price
Search for a book by title and distance

搜索与地球行星标题语义相似的书籍。返回按距离排序的前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
Search for a phrase using 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

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

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

总之,INORDER参数或$inorder查询属性要求查询项与具有相似顺序的项匹配。

Polygon Search with WITHIN, CONTAINS, INTERSECTS, and DISJOINT operators

查询多边形,这些多边形满足以下条件:

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

INTERSECTSDISJOINT 在 v2.10 版本中引入。

首先,使用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 ↑