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]
- 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
将结果限制为具有在min
和max
之间的数值的结果,如果numeric_attribute在FT.CREATE
中定义为数值属性。
min
和max
遵循ZRANGE
语法,可以是-inf
、+inf
,并使用(
表示不包含的范围。一个查询中支持对不同属性的多个数值过滤器。
自v2.10起已弃用:查询方言2解释了替代此参数的数值字段的查询语法。
GEOFILTER {geo_attribute} {lon} {lat} {radius} m|km|mi|ft
将结果过滤到从lon
和lat
开始的给定radius
范围内。半径以数字和单位给出。有关更多详细信息,请参见GEORADIUS
。
自v2.6起已弃用:查询方言3解释了替代此参数的地理空间字段的查询语法。
INKEYS {num} {attribute} ...
将结果限制为列表中指定的一组键。第一个参数必须是列表的长度且大于零。不存在的键将被忽略,除非所有键都不存在。
INFIELDS {num} {attribute} ...
过滤结果以仅显示文档中特定属性的内容,如title
或URL
。你必须包含num
,这是你过滤的属性数量。例如,如果你请求title
和URL
,那么num
就是2。
RETURN {num} {identifier} AS {property} ...
限制从文档返回的属性。num
是关键字后面的属性数量。如果 num
为 0,它的行为类似于 NOCONTENT
。
identifier
是属性名称(用于哈希和 JSON)或 JSON Path 表达式(用于 JSON)。
property
是结果中使用的可选名称。如果未提供,则在结果中使用 identifier
。
SUMMARIZE ...
仅返回包含匹配文本的属性部分。有关更多信息,请参见高亮显示。
HIGHLIGHT ...
格式化匹配文本的出现。有关更多信息,请参见高亮显示。
SLOP {slop}
是允许在查询术语之间出现的中间术语的数量。
假设你正在搜索一个短语hello world。
如果在hello和world之间出现了一些术语,大于0
的SLOP
允许这些文本属性匹配。
默认情况下,没有SLOP
约束。
INORDER
要求文档中的术语与查询中的术语顺序相同,无论它们之间的偏移量如何。通常与SLOP
一起使用。默认值为false
。
LANGUAGE {language}
在搜索查询扩展时,使用指定语言的词干提取器。如果查询中文文档,请设置为chinese
以正确分词查询词。默认为英语。如果发送了不支持的语言,命令将返回错误。有关语言列表,请参见FT.CREATE
。如果在索引创建时指定了LANGUAGE
,则无需在FT.SEARCH
中再次指定。
EXPANDER {expander}
使用自定义查询扩展器而不是词干提取器。参见扩展。
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的数组回复对,以及属性/值对的数组回复。
- 如果给出
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
属性中搜索术语dogs或cats,但给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"
现在,返回在hello和world之间有一个或更少单词的所有文档。
127.0.0.1:6379> FT.SEARCH memes '@phrase:(hello world)' NOCONTENT SLOP 1
1) (integer) 2
2) "s1"
3) "s2"
现在,返回所有在hello和world之间有三个或更少单词的文档。
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
查询多边形,这些多边形满足以下条件:
- 包含给定的地理形状
- 位于给定的地理形状内
- 与给定的地理形状相交
- 与给定形状不相交(没有共同点)
INTERSECTS
和 DISJOINT
在 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))"
另请参阅
相关主题
历史
- 从 Redis 2.0.0 版本开始:弃用了
WITHPAYLOADS
和PAYLOAD
参数 - 从 Redis 2.6 版本开始:已弃用
GEOFILTER
参数 - 从 Redis 2.10 版本开始:已弃用
FILTER
参数