全文搜索(FULLTEXT SEARCH)
为了在一个或多个列上使用全文搜索,在创建列的时候必须定义带有分析器的全文索引:或者使用CREATE TABLE或ALTER TABLE ADD COLUMN。获取更多的信息请查看
索引和全文索引。
MATCH谓词(MATCH Predicate)
概要(Synopsis)
MATCH (
{ column_ident | ( column_ident [boost] [, ...] ) }
, query_term
) [ using match_type [ with ( match_parameter [= value] [, ... ] ) ] ]
MATCH谓词在一个或多个索引列上执行全文搜索,而且支持不同的匹配技术。而且可以用来在geo_shape索引上执行地理搜索。
MATCH谓词的实际适用性取决于索引的类型。实际上,match_types和match_parameters的可用性依赖于具体索引。然而这一章,仅仅覆盖了在字符串列上MATCH谓词的使用。若要在geo_shape索引上使用MATCH,查看Geo Search。
若要在一个列上使用全文搜索,必须为这个列创建一个带分析器的全文索引。查看Indices和Fulltext Search获取更多详情。不同类型的索引和全文搜索有不同的目标,然而不能在一个MATCH谓词中查询不同索引类型的多个索引列。
获取匹配行的相关性,可以选择一个系统列_score。它包括一个和其它行的相关性的数字评分:值越高,行相关性越高。
cr> select name, _score from locations where match(name_description_ft, 'time') order by _score desc;
+-----------+------------+
| name | _score |
+-----------+------------+
| Bartledan | 0.52200186 |
| Altair | 0.4790727 |
+-----------+------------+
SELECT 2 rows in set (... sec)
MATCH以最简单的模式在一个单列上执行一个全文搜索。他使用query_term,若不提供分析器,则使用column_indet上设置分析器分析分词。分词器生成的token将和column_ident 索引匹配,若有一个匹配则MATCH将返回TRUE。
MATCH谓词也可以在带有一个单个query_term的多个列上执行全文搜索,而且可以给指定列添加权重,可以在每个column_ident上添加一个boost参数。与具有较高boost结果的列匹配,可以使此文档的_score值更高。
MATCH谓词也可以在多
match_type参数决定如何应用单个query_term以及如何计算结果_score。更多详情参见Match Types。
结果默认按_score排序,但是可以添加ORDER BY子句覆盖。
参数(Arguments)
参数 | 描述 |
---|---|
column_ident: | 对索引列或者类型为字符串类型的已有列的引用。默认情况下并不仅仅存储原始数据,每个列都将被索引化,因此不使用全文索引在一个字符串类型的列上匹配时等价于使用“=”操作符。为了执行全搜索使用带分析器的索引。 |
boost: | 一个列标识可以附带一个boost。是一个增加一个列和其他列之前平衡的一个权重因子。默认boost值为1。 |
query_term: | 字符串将被分析而且分词结果将和索引比较。用于搜索的tokens使用布尔操作符OR组合,除非使用其他可选操作符 |
match_type: | 可选的。默认为全文索引的best_fields。有关详情,请参阅匹配类型 |
注意
MATCH谓词只能在WHERE子句而且使用户创建的表上使用。系统表将不支持使用MATCH谓词。注意
一个MATCH谓词不能组合有连接关系的列。注意
如果MATCH谓词不能用于有连接的两个关系的列,如果它们不能在逻辑上分别应用于它们中的每一个。例如:This is allowed: FROM t1, t2 WHERE match(t1.txt, ‘foo’) AND match(t2.txt, ‘bar’); But this is not: FROM t1, t2 WHERE match(t1.txt, ‘foo’) OR match(t2.txt, ‘bar’);
匹配类型(Match Types)
匹配类型query_term的应用和_score的创建,从而影响到被认为跟相关的那些文档。默认全文索引的match_type是best_fields。
描述 | |
---|---|
best_fields: | 使用最匹配的列的_score。例如如果一个列包含查询分词query_term中所有token,则将认为比仅包含一个的其他列更相关。如果省略,则此类型是默认的。 |
most_fields: | 使用每一个匹配列的_score并使用它们的平均值 |
cross_fields: | 这个匹配类型将query_term分析成token,并且立即在所有给定列中搜索,如果它们是一个大的列(假设它们具有相同的分析器)。所有的token必须至少出现在一列,因此查询”foo bar“应该在一列中具有标记“foo”而且“bar”在同一列或者其他列。 |
phrase: | 此匹配类型和best_fields不同的是使用query_term构造查询短语。仅当列中的token与从query_term的中分析的列的顺序相同时,短语查询才会匹配。因此,查询“foo bar”(分析tokens:foo和bar)将仅仅匹配到包含这个顺序的两个token-之间没有其他token |
phrase_prefix: | 此类型和phrase类型大致一样,但是它允许在query_term的最后一个token上使用前缀匹配。例如,你查询“foo bar”,则其中一列必须按顺序包含foo而且有一个token以ba开始。因此,一个包含“foo baz”的列将匹配,而且“foo bar”也一样。 |
选项(Options)
匹配选项进一步使用确切的匹配类型区分匹配过程的方式。不是所有的选项使用于所有匹配类型。有关详细信息,查看以下选项。
描述 | |
---|---|
analyzer: | 分析器将query_term转化为token。 |
boost: | 此数字与匹配调用的结果评分相乘。如果此匹配调用与where子句猴子那个的其他条件一起使用。一个1.0以上的值将增加对整个查询的_score的影响,一个1.0以下的值将降低此影响 |
cutoff_frequency: | token的频率是一个token在一个列中出现的频率。这个选项指定一个最小的token频率,不包括来自整个具有很高_score的token。仅包括它们的_score若果一个较小频率的token也被匹配。此项配置将用于抑制像这样的高频分词引起的一个匹配。 |
fuzziness: | 可用于执行模糊全文搜索。在数字列上使用数字,在时间戳列上使用一个龙类型的毫秒数,在string列上使用一个数字指定允许Levenshtein编辑的最大距离。使用prefix_length,fuzzy_rewrite和max_expansions微调模糊匹配过程。 |
fuzzy_rewrite: | 和rewrite相同但是仅仅作用于使用模糊的查询。 |
max_expansions: | 当使用fuzziness 或者 phrase_prefix时,这个选项控制一个token将会扩展出多少个可能的token。fuzziness 控制原始token和一组扩展的token之间有多大的距离或不同。选项控制此组可获得的大小。 |
minimum_should_match: | 来自query_term的token数,当使用or时使用。默认为1。 |
operator: | 可以是or或者and。默认是or。用于组合query_term的token。如果使用and,必须匹配每个出自query_term的token。如果使用or,仅仅匹配minimum_should_match数量必须匹配。 |
prefix_length: | 当使用fuzziness选项 或者与带有phrase_prefix的选项时,这个选项控制被认为相似(同样的前缀或者模糊匹配距离/不同)的token的公共前缀的长度。 |
rewrite: | 当使用phraseprefix ,前缀查询将使用所有可能分词来构造,并且将其写入到另一种查询中以计算其分数。可能的值有constant_score_auto, constant_score_boolean, constant_score_filter, scoring_boolean,top_terms_N , top_terms_boost_N. 常量constant...值可以和boost选项一起使用,以便为前缀匹配或模糊匹配的行设置一个常量_score。 |
slop: | 当为短语匹配时,这个选项控制短语匹配的精确度(临近搜索)。如果设置为0(默认值),则分词必须按确切的顺序。如果两个转置的分词匹配,则应该设置一个最小的slop值2。仅仅应用phrase和phrase_prefix查询。就像一个slop 2的例子,查询“foo bar”将不仅匹配foo bar,还会匹配foo what bar。 |
tie_breaker: | 当使用best_fields, phrase 或者 phrase_prefix,则其他列的_score将会乘以此值而且加到匹配最好的列的_score上。默认是0.0。不适用于most_fields类型,因为如果此类型被执行,就像是它的tie_breaker的值为1.0。 |
zero_terms_query: | 如果query_term的分析结果没有生成token,则不会匹配任何文档。如果这里给的是all,则匹配所有文档。 |
用法(Usage)
使用MATCH谓词进行全文搜索:
cr> select name from locations where match(name_description_ft, 'time') order by _score desc;
+-----------+
| name |
+-----------+
| Bartledan |
| Altair |
+-----------+
SELECT 2 rows in set (... sec)
和搜索字符串匹配到的行将返回TRUE。更多详情查看等值匹配,相关的列,_score可以被选中:
cr> select name, _score
... from locations where match(name_description_ft, 'time') order by _score desc;
+-----------+------------+
| name | _score |
+-----------+------------+
| Bartledan | 0.52200186 |
| Altair | 0.4790727 |
+-----------+------------+
SELECT 2 rows in set (... sec)
注意
_score不是一个绝对值。它只是相对于其它行的一个设置。
如果一个搜索跨多个列的内容则应该有两种可能:
在你的表中使用一个复杂的索引列。查看一个复杂索引的定义。
在多列上使用MATCH谓词
当查询多列时,有许多方式计算相关度 _score。这些不同的技术讲座匹配类型。
为了增加一个列匹配非常好的行相关度,使用best_fields(默认)。如果匹配比较好的行遍布所有包含的列,则应该有更多的相关度,使用most_fields。要想像使用一列一样查询多行,使用cross_fields。为了查询匹配的短语使用phrase或者phrase_prefix:
cr> select name, _score from locations
... where match(
... (name_description_ft, race['name'] 1.5, kind 0.75),
... 'end of the galaxy'
... ) order by _score desc;
+-------------------+------------+
| name | _score |
+-------------------+------------+
| NULL | 0.91878563 |
| Altair | 0.11727207 |
| Aldebaran | 0.10617954 |
| North West Ripple | 0.06788038 |
| Outer Eastern Rim | 0.06788038 |
+-------------------+------------+
SELECT 5 rows in set (... sec)
cr> select name, description, _score from locations
... where match(
... (name_description_ft), 'end of the galaxy'
... ) using phrase with (analyzer='english', slop=4);
+------+-------------------------+----------+
| name | description | _score |
+------+-------------------------+----------+
| NULL | The end of the Galaxy.% | 2.296235 |
+------+-------------------------+----------+
SELECT 1 row in set (... sec)
有大量的选项来优化你现有的全文搜索。一个详细的引用可以在查看MATCH谓词。
否定搜索(Negative Search)
A negative fulltext search can be done using a NOT clause:
否定搜索可以使用NOT子句来实现:
cr> select name, _score from locations
... where not match(name_description_ft, 'time')
... order by _score, name asc;
+------------------------------------+--------+
| name | _score |
+------------------------------------+--------+
| | 1.0 |
| Aldebaran | 1.0 |
| Algol | 1.0 |
| Allosimanius Syneca | 1.0 |
| Alpha Centauri | 1.0 |
| Argabuthon | 1.0 |
| Arkintoofle Minor | 1.0 |
| Galactic Sector QQ7 Active J Gamma | 1.0 |
| North West Ripple | 1.0 |
| Outer Eastern Rim | 1.0 |
| NULL | 1.0 |
+------------------------------------+--------+
SELECT 11 rows in set (... sec)
通过_score过滤(Filter By _score)
可以通过_score列来过滤结果,但是它的值是一个相对于所有结果中最高分而计算的值,因此从来不是绝对的或者可比较的,在排序之外的使用性是非常有限的。在_score列上使用“>=”操作符过滤将不会有什么意义而且可能导致不可预测的结果集。
无论若何,我们在这里作一个示范:
cr> select name, _score
... from locations where match(name_description_ft, 'time')
... and _score >= 0.8 order by _score;
+-----------+------------+
| name | _score |
+-----------+------------+
| Bartledan | 0.8679331 |
| Altair | 0.88735807 |
+-----------+------------+
SELECT 2 rows in set (... sec)
你可能注意到这点,_score值对同样查询文本和文档的值已经改变,因为它是一个相对所有结果的比率,通过_score过滤,‘all results’已经改变。
警告
如上所述,_score是一个相对数字而且在搜索中不可比。因此,极大阻止了过滤。