dot 快捷的未来正在您的所在城市举办活动。

加入我们参加 Redis Released

RediSearch 1.4:音标和拼写检查

每次新版本的 RediSearch 发布时,我们都感到很兴奋——我们刚刚发布了 1.4 版(是的,我们跳过了 1.3 版,以适应新的版本方法)。此新版本增加了两项关键特性,为查询添加了不少智能

  • 拼写检查和自定义词典
  • 音标(发音相似)匹配

拼写检查

首先,让我们了解一下拼写检查。从广义上讲,每个人都知道拼写检查是什么,但让我们研究一下它在搜索引擎环境中如何工作。最好将它视为可支持“您要查找的是不是”功能的基础。

以这个特定查询为例

“霍克耶 斯蒂克”

作为人类,您可能知道这是“曲棍球杆”的意思,但如果没有拼写检查,返回的结果就不理想。这里说明了 RediSearch 1.4 如何帮助您。首先,您通过 FT.SPELLCHECK 命令运行查询;如果所有拼写都正确,则不会返回任何内容 (空列表或集)。如果传入 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)

(空列表或集) 意味着拼写检查认为它是拼写错误的,但它没有更正。要补救这种情况,我们将在词典中添加一些俚语:

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

现在,我们可以在查询中运行拼写检查并 排除 这些术语。此处的术语有点混乱,但可以将其视为排除要拼写检查的词语,例如,假设它们拼写正确。

127.0.0.1:6379>  FT.SPELLCHECK incidents "Toonie toque kerfuffle" TERMS EXCLUDE slang
(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)

因此,拼写检查已识别出该词语拼写错误,但不知道如何更正它。为此,您需要 包含 词典并 排除 词典。

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 使用称为双元音素算法的算法执行此操作,该算法具有引人入胜的历史,可以随时查找一下。

首先,你需要定义想要按音标编制的字段(显然只有TEXT字段)。让我们创建一个具有两个音标字段的小型索引:

所以,现在我们已在名称和母校字段中添加了文档,从而启用了音标。让我们添加一些文档

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”,它还同时记录了它们的元音素代码。在此情况下,“jon”和“john”都翻译为JNPHONETIC

> 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”?这是因为它们具有相同的双元音素翻译。在这一点上,你可能会在你的办公桌前为搜索引擎中的音标匹配所带来的奇迹而雀跃。你所有的问题都解决了!

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

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”看起来和听起来一点也不像!这不是一个缺陷,而是双元音素算法的弱点,它会去掉一些信息并强调其他信息。元音素应谨慎用于不太可能包含同音异义词的字段中。你还可以使用属性来关闭音标搜索

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 有一些激动人心的功能,可以为搜索增加大量的灵活性。这些功能抓住了好的搜索引擎的本质:它可以适应人为错误,但不会忽视用户的真实意图。