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。由于位置不匹配,我们不能谈论 2 个匹配单词形成子序列的情况。
LCS 的一种更限制性版本是 LCCS (最长公共连续子序列)。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