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
将结果限制为那些具有介于 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 路径表达式(对于 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
来计算结果集中的文档数量,而不实际返回它们。
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
属性中搜索词语dogs或cats,但给与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"
现在,返回所有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
同样,如果你使用设置为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))"
另请参见
相关主题
历史
- 从 Redis 版本 2.0.0 开始:弃用
WITHPAYLOADS
和PAYLOAD
参数 - 从 Redis 版本 2.6 开始:弃用
GEOFILTER
参数 - 从 Redis 版本 2.10 开始:弃用
FILTER
参数