Java中字符串的模糊字符串匹配

时间:2017-03-13 09:32:23

标签: java string fuzzy-search

我有一个非常大的存储在NoSQL DB中的字符串列表。传入查询是一个字符串,我想检查列表中是否存在此字符串。如果完全匹配,这非常简单。 NoSQL DB可能将String作为主键,我将检查是否有任何记录将该字符串作为主键。但我也需要检查模糊匹配。

有一种方法遍历该列表中的每个字符串,并使用列表中的字符串检查输入字符串的Levenshtein距离,但这种方法将导致O(n)复杂性并且列表的大小非常大(1000万)甚至可能会增加。这种方法会导致我的解决方案的延迟更高。

有没有更好的方法来解决这个问题?

3 个答案:

答案 0 :(得分:1)

首先,如果您正在进行搜索,那么您应该使用搜索引擎(ElasticSearch几乎是默认搜索引擎)。他们擅长这一点而你并没有重新发明轮子。

其次,您正在寻找的技术称为stemming。与原始String一起,在数据库中保存一个规范化的字符串。使用相同的机制规范化搜索查询。这样你就可以获得更好的搜索结果。显然,这是搜索引擎在引擎盖下使用的技术之一。

答案 1 :(得分:1)

使用Solr(或Lucene)可能是适合您的解决方案吗?

  

Lucene支持基于Levenshtein距离或编辑距离算法的模糊搜索。要进行模糊搜索,请在单个单词Term的末尾使用波浪号“〜”符号。例如,要搜索拼写为“漫游”的术语,请使用模糊搜索:

roam~
     

此搜索会找到泡沫和漫游等字词。

     

从Lucene 1.9开始,附加(可选)参数可以指定所需的相似性。该值介于0和1之间,值接近1,仅匹配具有更高相似度的项。例如:

roam~0.8 

https://lucene.apache.org/core/2_9_4/queryparsersyntax.html

答案 2 :(得分:1)

由于您发现的原因,模糊匹配很复杂。出于性能原因,计算搜索项与数据库术语的每个组合的距离度量标准是不切实际的。

解决方法通常是使用n-gram索引。这可以单独使用以提供结果,也可以作为过滤器来减少可能结果的大小,以便您可以计算更少的距离分数。

所以基本上,如果你有一个单词" stack"你把它分成n-gram(通常是三元组),例如" s"," st"," sta"," ack",& #34; ck"," k"。您可以将数据库中的数据库与数据库行进行索引。然后,对输入执行相同操作,并查找具有相同匹配n-gram的数据库行。

这一切都很复杂,你最好的选择是使用现有的实现,如Lucene / Solr,它将为你做n-gram的东西。当我使用专有解决方案时,我自己还没有使用它,但是有一个可能与之相关的stackoverflow问题:

Return only results that match enough NGrams with Solr

某些数据库似乎实现了n-gram匹配。以下是Sybase页面的链接,该页面提供了一些讨论:

Sybase n-gram text index

不幸的是,关于n-gram的讨论将是一个很长的帖子,我没有时间。可能它在stackoverflow和其他网站上的其他地方讨论过。我建议谷歌搜索这个术语并阅读它。