⚠️ 此页面为自动翻译,翻译可能不完美。

Relevance scoring in Manticore : part II

在关于相关性评分的第二部分中,我们讨论了如何利用位置信息进行匹配和评分。

了解字段中词语的位置信息非常重要,可以提供更好的相关性。位置信息允许使用一系列文本运算符,这些运算符可以通过词语在字段中的相对位置进行匹配,或者通过计算字段内找到的关键词之间的距离,或与输入查询进行比较。基于位置的最常用运算符之一是短语运算符 - "A B"短语匹配具有限制性,因为它们强制要求关键词按照查询中指定的方式匹配。这意味着关键词必须相邻,并且顺序与查询中的一致。

知道词语的位置后,我们可以执行匹配以查找字段是否以特定词语开头或结尾,使用起始 (^) 和结束 ($) 运算符 。还可以通过在字段名称运算符后指定限制,将字段内的搜索限制为仅当词语出现在字段的前N个词语中时才匹配。例如,可以使用 @myfield [10] word。我们还可以通过使用顺序运算符确保输入词语按特定顺序出现 - word1 << word2 << word3,或者如果输入词语在字段中以一定邻近度出现,可以使用邻近运算符:"word1 word2"~10

邻近匹配允许在字段中匹配的关键词之间最多有N个词语。例如,"A B C"~4 匹配 "A D E B F C",但不匹配 "A D E B F G C"

对于更宽松的邻近度,可以使用 NEAR 运算符。与邻近运算符处理一组关键词不同,NEAR 处理两个操作数,这两个操作数可以是词语或其他子表达式。例如,可以执行 "A B" NEAR/2 C - 如果短语 "A B"C 之间最多有 2 个词语,则匹配有效。类似地,还存在 NOTNEAR 运算符,它仅在操作数(词语或子表达式)之间有最小数量的词语时才匹配。

多种相关性度量使用词语位置来计算查询与文档之间的距离。LCS(最长公共子序列)给出文档与查询之间最大逐字匹配的长度。这意味着我们尝试查找输入查询的子序列是否存在于文档中。如果查询有完全匹配,LCS 的最大值是查询中的词语数量。子序列的 LCS 值取决于其长度,最低值为 1,即当词语被找到但不形成超过 1 个词语的子序列时。需要注意的是,子序列不需要由相邻匹配的词语组成。例如,如果输入为 A B C,而在文档中找到 A D C,该子序列将获得 2 分,因为 A 和 C 按顺序出现在查询中的相同位置:

mysql> SELECT *,WEIGHT() FROM testrt WHERE MATCH('hello world program') OPTION ranker=expr('top(lcs)');
+------+--------------------------+----------------------------+----------+
| id   | title                    | content                    | weight() |
+------+--------------------------+----------------------------+----------+
|    6 | hello world program      | just some content          |        3 |
|    4 | hello test program       | just some world content    |        2 |
|    5 | hello test world program | just some content          |        2 |
|    9 | hello world              | just program world content |        2 |
|    7 | hello test world         | just program some content  |        1 |
|    8 | test program hello       | just some world content    |        1 |
+------+--------------------------+----------------------------+----------+
6 rows in set (0.00 sec)

文档 4 在标题中的 LCS 值为 2,因为我们的查询是 hello world program,而子序列是 hello test program - 即使我们有一个不在匹配列表中的词语,helloprogram 词语仍位于它们的位置(1 和 3),并且它们之间。

文档 7 中的 hello test world 虽然有 2 个词语(helloworld)按顺序出现,但它们的位置是 1 和 3,而在查询中它们的位置是 1 和 2。由于位置不匹配,我们不能说这两个匹配的词语形成了一个子序列。

LCCS(最长公共连续子序列)是 LCS 的一种更严格的版本。LCCS 仅对由相邻词语组成的子序列进行评分。为了说明差异,我们可以使用之前的例子,但现在使用 lccs:

mysql> select *,weight() from testrt where match('hello world program') option ranker=expr('top(lccs)');
+------+--------------------------+----------------------------+----------+
| id   | title                    | content                    | weight() |
+------+--------------------------+----------------------------+----------+
|    6 | hello  world program     | just some content          |        3 |
|    5 | hello test world program | just some content          |        2 |
|    9 | hello world              | just program world content |        2 |
|    4 | hello test program       | just some world content    |        1 |
|    7 | hello test world         | just program some content  |        1 |
|    8 | test program hello       | just some world content    |        1 |
+------+--------------------------+----------------------------+----------+
6 rows in set (0.00 sec)

现在,文档 4 的 LCS=2,但 LCCS=1,因为虽然它有一个子序列且词语位置相同,但这些词语并不相邻。
LCS 和 LCCS 在公式中将每个关键词计为 1,而不考虑词语的重要性(稀有或常见程度)。LCCS 的一种变体称为 WLCCS 或加权最长公共连续子序列,它可以将关键词的 IDFs 相加,而不是简单的计数。与 LCS 和 LCCS 不同,WLCCS 使用浮点值,因为 IDFs 以浮点数表示,输出取决于数据本身(因为 IDF 是相对于当前索引的相对度量)。WLCCS 会为包含稀有词语的子序列提供更好的值,并可以对使用 LCS 或 LCCS 否则评分较低的文档进行更高排名。

我们之前讨论过一个运算符,它仅在关键词开始字段时匹配。第一个出现的位置也可以用于相关性计算,因为这表明如果关键词在字段中更早出现,甚至在字段的开头,它对该字段的重要性更大。min_hit_pos 表示第一个匹配关键词的位置。在排名表达式中,我们可以添加一个检查 min_hit_pos==1 来检查第一个匹配的关键词是否出现在字段的开头。

最早的位置也可以应用于子序列。想象一下,我们有多个文档,它们提供了与查询(部分或全部)匹配的子序列,我们想知道哪些文档的子序列在字段中出现得更早。我们可以使用 min_best_span_pos 来实现这一点,它会给出字段中最佳子序列(按 LCS 计算)的首次出现位置。

安装Manticore Search

安装Manticore Search