dot Redis 8 已发布,而且它是开源的

了解更多

RediSearch 1.4:语音匹配和拼写检查

当 RediSearch 发布新版本时总是令人兴奋——我们刚刚发布了 1.4 版本(是的,我们跳过了 1.3 版本,以便与新的版本控制方法保持一致)。这个新版本有两个关键特性,为查询增加了不少智能。

  • 拼写检查和自定义词典
  • 语音(听起来像的)匹配

拼写检查

让我们首先来看看拼写检查。从宏观角度来看,每个人都知道拼写检查是什么,但让我们研究一下它在搜索引擎环境中的工作原理。最好将其视为驱动“您是不是想找”功能的原始功能。

例如,请看这个特定的查询:

“Hockye stik”

作为人类,你可能知道这指的是“曲棍球棒”(Hockey stick),但如果没有拼写检查,返回的结果不会很好。RediSearch 1.4 可以这样帮助你。首先,你通过 FT.SPELLCHECK 命令运行查询;如果所有内容拼写都正确,它将返回空 (empty list or set)。如果传入 FT.SPELLCHECK 的查询包含似乎拼写错误的词语,RediSearch 将返回哪些词语有问题以及一些建议。

让我们在一个已填充的数据集上运行上面的示例:

127.0.0.1:6379> ft.spellcheck incidents "Hockye stik"
1) 1) "TERM"
   2) "hockye"
   3) 1) 1) "7.3874642939225789e-05"
         2) "hockey"
2) 1) "TERM"
   2) "stik"
   3) 1) 1) "5.7458055619397838e-05"
         2) "stick"

非常简单!每个拼写错误的词语都会返回“TERM”和拼写错误的词语本身,然后是任何替代词以及它们各自的置信度分数,按最高分排序。示例中只有一个替代词,但你当然可以有更多。

假设你使用此命令创建了一个保安事故报告索引:

127.0.0.1:6379> ft.create incidents SCHEMA report text
OK

该功能假定索引中存在的任何词语都拼写正确(例如,没有内置的有效词典)。但是,你可能有一些你想假定拼写正确但尚未索引的词语。此索引将包含涉及安全事故的人员的报告,并且可能包含 许多俚语

127.0.0.1:6379> ft.spellcheck incidents "Toonie toque kerfuffle"
1) 1) "TERM"
   2) "toonie"
   3) (empty list or set)
2) 1) "TERM"
   2) "toque"
   3) (empty list or set)
3) 1) "TERM"
   2) "kerfuffle"
   3) (empty list or set)

(empty list or set) 意味着拼写检查认为它拼写错误,但没有更正建议。为了解决这种情况,我们将向词典中添加一些俚语:

127.0.0.1:6379> FT.DICTADD slang timmies toque toonie serviette kerfuffle chesterfield
(integer) 6

现在,我们可以在查询上运行拼写检查并排除 (EXCLUDE)这些术语。这里的术语有点令人困惑,但可以将其理解为排除词语被拼写检查,即假定它们拼写正确。

127.0.0.1:6379>  FT.SPELLCHECK incidents "Toonie toque kerfuffle" TERMS EXCLUDE slang
(empty list or set)

响应 (empty list or set) 意味着传入字符串中的所有词语都没有拼写错误。但这只能帮我们到这里。如果这些新词语中的一个拼写错误怎么办?让我们看看。

127.0.0.1:6379> FT.SPELLCHECK incidents "Tooni toque kerfuffle" TERMS EXCLUDE slang
1) 1) "TERM"
   2) "tooni"
   3) (empty list or set)

因此,拼写检查已经识别出该词拼写错误,但它不知道如何纠正。为此,你需要包含 (INCLUDE)词典,同时也排除 (EXCLUDE)它。

127.0.0.1:6379> FT.SPELLCHECK incidents "Tooni toque kerfuffle" TERMS EXCLUDE slang TERMS INCLUDE slang
1) 1) "TERM"
   2) "tooni"
   3) 1) 1) "0"
         2) "toonie"

现在你可以看到它正在纠正拼写。

重申一点很重要:如果你已经有包含这些术语的文档,则无需费心使用自定义词典。假设你有一个这样的文档:

127.0.0.1:6379> FT.ADD incidents report42 1 FIELDS report "Complainant A described that he went to Timmies in his favourite toque, gave the cashier a toonie for his double-double and grabbed for a serviette, while Defendant B tried to steal his hat. Complainant A and Defendant B ended up in a real kerfuffle falling onto the chesterfield."

由于此报告包含所有这些俚语,它们会自动填充到拼写检查中,无需自定义词典,无论是包含还是排除检查。

127.0.0.1:6379> FT.SPELLCHECK incidents "toonie tque kerfuffle"
1) 1) "TERM"
   2) "tque"
   3) 1) 1) "1"
         2) "toque"

因此,对于尚未在现有文档中提及的特定领域术语,最好使用自定义词典。

语音匹配

语音匹配解决了这样一个典型问题:搜索名为“Jon”的人,但输入的是“John”——听起来一样,但拼写不同。如果你想深入探究,可以试试找出为什么这两种拼写都作为现代英语名字存在。跑题了。

这是一个棘手的搜索问题,因为即使搜索引擎使用的技巧(如词干提取)也无济于事。为了解决这个问题,搜索引擎可以使用算法,根据语言的发音规则将文本分解为特定语言的代码。RediSearch 使用一种称为 Double Metaphone 的算法来实现这一点,它有一段引人入胜的历史,不妨找时间了解一下。

首先,你需要定义要进行语音索引的字段(显然只能是TEXT 字段)。让我们创建一个包含两个语音字段的小索引:

因此,当我们添加文档时,现在已经在 name 和 almamater 字段上启用了语音匹配。让我们添加一些文档:

127.0.0.1:6379> FT.ADD complainants foo64 1 FIELDS name "jon" almamater Trent
OK
127.0.0.1:6379> FT.ADD complainants foo65 1 FIELDS name "john" almamater Toronto
OK

当 RediSearch 将文档添加到索引时,它不仅仅记录“jon”或“john”,它会用它们的 metaphone 代码记录两者。在这种情况下,“jon”和“john”都转换为 JN。 要搜索这些词语,你只需要在标记为 PHONETIC的特定字段上进行搜索。

> FT.SEARCH complainants "@name:john"
1) (integer) 2
2) "foo64"
3) 1) "name"
   2) "jon"
   3) "almamater"
   4) "Trent"
4) "foo65"
5) 1) "name"
   2) "john"
   3) "almamater"
   4) "Toronto"

看到它是如何匹配“john”和“jon”的吗? 这是因为它们具有相同的 Double Metaphone 转换。此时,你可能会因为搜索引擎中的语音匹配这一奇妙功能而在办公桌旁手舞足蹈。你的所有问题都解决了!

没那么快——语音匹配应该谨慎使用。它是一个非常锋利的工具,但也可能伤到你。让我们以我们的微示例中的第二个字段为例:

127.0.0.1:6379> FT.SEARCH complainants "@almamater:trent"
1) (integer) 2
2) "foo65"
3) 1) "name"
   2) "john"
   3) "almamater"
   4) "Toronto"
4) "foo64"
5) 1) "name"
   2) "jon"
   3) "almamater"
   4) "Trent"
127.0.0.1:6379> FT.SEARCH complainants "@almamater:toronto"
1) (integer) 2
2) "foo64"
3) 1) "name"
   2) "jon"
   3) "almamater"
   4) "Trent"
4) "foo65"
5) 1) "name"
   2) "john"
   3) "almamater"
   4) "Toronto"

“Trent”和“Toronto”看起来和听起来完全不像!这不是一个 bug,而是 Double Metaphone 算法的一个弱点,它会丢弃一些信息并强调其他信息。Metaphone 应该谨慎用于那些不太可能包含发音相似词语的字段。你还可以使用一个属性来关闭语音搜索。

127.0.0.1:6379> FT.SEARCH complainants "@almamater:(toronto=>{$phonetic:false})"
1) (integer) 1
2) "foo65"
3) 1) "name"
   2) "john"
   3) "almamater"
   4) "Toronto"

RediSearch 1.4 包含一些令人兴奋的功能,为搜索增加了巨大的灵活性。这些功能触及了一个优秀搜索引擎的核心:它在不忽视用户真正意图的情况下容纳人为错误。