Apache Lucene 和通过候选词列表在文本文档中进行模糊搜索
Apache Lucene and fuzzy search in text document by list of candidate words
我有经过 OCR 处理后的文本文件。由于原始文档的图像质量不佳,此文本经常包含损坏的文字。
我还有一个有效公司名称的列表,可以出现在上述文本文件中。
根据这个公司名称列表,我想确定拥有扫描文档的公司名称(即使公司名称在文本文件中略有损坏)。
我想对扫描的文档进行类似模糊搜索的操作,以便尝试从那里的列表中找到公司名称。获胜者将是匹配分数最高的公司名称。
我想我可以为此目的使用 Apache Lucene 功能。您能否提出建议,或者可以使用 Apache Lucene 来实现,如果可以,请给出示例。
提出的想法如下。您可以为每个公司名称(甚至描述和任何有用的信息)创建一个 Lucene 文档
Document doc = new Document();
doc.add(new TextField("text", "BlueCross BlueShield", Field.Store.YES));
writer.addDocument(doc);
添加所有公司后,您可以将获得的文本用作 MoreLikeThis 查询。 MLT背后的想法如下,它试图找到相似的文本。
可以创建如下:
MoreLikeThis mlt = new MoreLikeThis(reader);
mlt.setAnalyzer(analyzer);
mlt.setMinDocFreq(0);
mlt.setMinTermFreq(0);
mlt.setMinWordLen(0);
final Query query = mlt.like("text", new StringReader("BlueCros BlueShield Customer Service \n" +
" 1-800-521-2227 \n" +
" of Texas Preauth-Medical 1-800-441-9188 \n" +
" Preauth-MH/CD 1-800-528-7264 \n" +
" Blue Card Access 1-800-810-2583 "));
System.out.println(query);
TopDocs results = searcher.search(query, 5);
总的来说,我们正在做反向匹配,它应该对你有帮助,我在那里做了一些测试。棘手的部分是模糊匹配,因为 MLT 不提供它,所以在这种情况下,可以重写 MLT 查询以将其包装到 FuzzyQuery 中。
BooleanQuery.Builder builder = new BooleanQuery.Builder();
if (query instanceof BooleanQuery) {
final List<BooleanClause> clauses = ((BooleanQuery) query).clauses();
for (BooleanClause bc : clauses) {
Query q = bc.getQuery();
if (q instanceof TermQuery) {
builder.add(new FuzzyQuery(((TermQuery) q).getTerm(), 2), bc.getOccur());
} else {
builder.add(bc);
}
}
}
此外,使用适当的分析器非常重要 - 在 BlueCross
的简单情况下,我提供了一个在大写更改时拆分标记的分析器。在此处添加同义词可能会有所帮助
完整代码示例位于here
我有经过 OCR 处理后的文本文件。由于原始文档的图像质量不佳,此文本经常包含损坏的文字。
我还有一个有效公司名称的列表,可以出现在上述文本文件中。
根据这个公司名称列表,我想确定拥有扫描文档的公司名称(即使公司名称在文本文件中略有损坏)。
我想对扫描的文档进行类似模糊搜索的操作,以便尝试从那里的列表中找到公司名称。获胜者将是匹配分数最高的公司名称。
我想我可以为此目的使用 Apache Lucene 功能。您能否提出建议,或者可以使用 Apache Lucene 来实现,如果可以,请给出示例。
提出的想法如下。您可以为每个公司名称(甚至描述和任何有用的信息)创建一个 Lucene 文档
Document doc = new Document();
doc.add(new TextField("text", "BlueCross BlueShield", Field.Store.YES));
writer.addDocument(doc);
添加所有公司后,您可以将获得的文本用作 MoreLikeThis 查询。 MLT背后的想法如下,它试图找到相似的文本。
可以创建如下:
MoreLikeThis mlt = new MoreLikeThis(reader);
mlt.setAnalyzer(analyzer);
mlt.setMinDocFreq(0);
mlt.setMinTermFreq(0);
mlt.setMinWordLen(0);
final Query query = mlt.like("text", new StringReader("BlueCros BlueShield Customer Service \n" +
" 1-800-521-2227 \n" +
" of Texas Preauth-Medical 1-800-441-9188 \n" +
" Preauth-MH/CD 1-800-528-7264 \n" +
" Blue Card Access 1-800-810-2583 "));
System.out.println(query);
TopDocs results = searcher.search(query, 5);
总的来说,我们正在做反向匹配,它应该对你有帮助,我在那里做了一些测试。棘手的部分是模糊匹配,因为 MLT 不提供它,所以在这种情况下,可以重写 MLT 查询以将其包装到 FuzzyQuery 中。
BooleanQuery.Builder builder = new BooleanQuery.Builder();
if (query instanceof BooleanQuery) {
final List<BooleanClause> clauses = ((BooleanQuery) query).clauses();
for (BooleanClause bc : clauses) {
Query q = bc.getQuery();
if (q instanceof TermQuery) {
builder.add(new FuzzyQuery(((TermQuery) q).getTerm(), 2), bc.getOccur());
} else {
builder.add(bc);
}
}
}
此外,使用适当的分析器非常重要 - 在 BlueCross
的简单情况下,我提供了一个在大写更改时拆分标记的分析器。在此处添加同义词可能会有所帮助
完整代码示例位于here