【问题标题】:Fuzzy Queries in LuceneLucene 中的模糊查询
【发布时间】:2010-07-28 23:10:31
【问题描述】:

我在 JAVA 中使用 Lucene,并根据公司名称在我们的数据库中索引一个表。在索引之后,我希望对我们希望输入数据库的值进行模糊匹配(Levenshtein 距离)。原因是我们不想因为拼写错误而被骗。

例如,如果我的公司名称为“Widget Makers XYZ”,我不想插入“Widget Maker XYZ”。

从我读到的 Lucene 的模糊匹配算法应该给我一个介于 0 和 1 之间的数字,我想做一些测试,然后确定和足够的值让我们确定什么是有效的或无效的。

问题是我被卡住了,在互联网上到处搜索后,需要 StackOverflow 社区的帮助。

就像我说的,我已经索引了公司名称的数据库,然后有以下代码:

IndexSearcher searcher = new IndexSearcher(directory);  

new QueryParser(Version.LUCENE_30, "company", analyzer);

Query fuzzy_query = new FuzzyQuery(new Term("company", "Center"));

后来遇到这个问题,基本不知道怎么获取模糊匹配值。我知道代码必须如下所示,但是似乎没有收集器适合我的需求。 (如你所见,我现在只能计算匹配的数量,这对我来说没用)

TopScoreDocCollector collector = TopScoreDocCollector.create(10, true);

searcher.search(fuzzy_query, collector);

System.out.println("\ncollector.getTotalHits() = " + collector.getTotalHits());

我也无法使用 Lucene 文档中显示的 ComplexPhraseQueryParser 类。我在做:

import org.apache.lucene.queryParser.*;

有人知道为什么它无法访问或我做错了什么吗?抱歉问题太长了。

【问题讨论】:

    标签: java indexing lucene


    【解决方案1】:

    你不需要 Lucene 来获得分数。看看Simmetrics library,使用起来非常简单。只需添加 jar 并这样使用它:

    Levenstein ld = new Levenstein ();
    float sim = ld.GetSimilarity(string1, string2);
    

    另外请注意,根据数据类型(即较长的字符串、# 空格等),您可能需要查看其他算法,例如 Jaro-Winkler、Smith-Waterman 等。

    您可以使用上述方法确定将模糊重复字符串折叠成一个“主”字符串,然后进行索引。

    【讨论】:

    • 我正在查看 Simmetrics 库,它看起来确实很有前途。我想使用 Lucene 是因为它的索引能力,因为我正在搜索一个包含 60K 或更多公司名称的数据库。 Simmetrics 在任何级别上都与 Lucene 兼容吗?
    • 嗯不知道为什么你需要 SimMetrics 来兼容——不管这意味着什么。编写一个应用程序来循环遍历数据库行并使用 Simmetrics 通过相似性对名称进行聚类 - 您可以使用各种阈值来确定最佳拟合。因此,您创建了一个查找表“Widget Makers XYZ”,-
    • 抱歉不清楚,我的意思是 SimMetrics 可以从 Lucene 创建的索引中读取吗?我宁愿不创建任何不需要的或临时的表,除非我必须这样做。并且想要一个快速的比赛时间。我的程序布局是: 1) 使用 Lucene 按名称索引所有公司,将索引存储在 RAM 中。 2) 每个想要插入的公司名称都必须满足特定的算法要求,即 TBD,但将依赖 Leinshtein 算法,然后(如果需要)双变音位算法。现在可能还有一些来自 SimMetrics 库。
    • 不确定 Simmetrics 是否可以从 Lucene 读取数据,可能不行。您可以采用以下两步方法: 1. 创建一个索引并为每个需要插入的公司查询索引(这应该会给您一个可行的子集,例如 10 个结果来运行字符串 dist 比较) 2. 比较新的公司命名 10 个结果并查看 new 是否通过阈值或是骗子。 BTW Levenstein 包含在 SimMetrics 中,因此您无需自己实现。
    【解决方案2】:

    您可以通过以下方式获取匹配值:

    TopDocs topDocs = collector.topDocs();
    for(ScoreDoc scoreDoc : topDocs.scoreDocs) {
        System.out.println(scoreDoc.score);
    }
    

    【讨论】:

    • 采集器应该是什么类型的?当我运行这个时,我没有得到任何输出。
    猜你喜欢
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 2015-07-03
    • 2012-05-05
    • 2014-05-04
    • 1970-01-01
    • 2021-07-01
    相关资源
    最近更新 更多