总结:Lucene 将负责为与您的输入短语更匹配的索引文本分配更高的匹配分数,而无需您自己“创建所有有意义的短语”。
从简单开始
我建议你从一个基本的 Lucene 分析器开始,看看它有什么效果。它很有可能会满足您的需求。
如果这不能给您带来满意的结果,那么您当然可以研究更具体/有针对性的分析器/标记器/过滤器(例如,如果您需要分析非拉丁字符集)。
如果不更详细地查看源数据和短语匹配要求,很难更具体。
但是,话虽如此,这里有两个示例(我假设您基本熟悉如何创建 Lucene 索引,然后对其进行查询)。
所有代码均基于 Lucene 8.4。
CAVEAT - 我不熟悉 Lucene 的 Python 实现。因此,抱歉,我的示例是用 Java 编写的,而不是 Python(因为您的问题已被标记)。我想这些概念在某种程度上是可以翻译的。抱歉,如果这对您不利。
基本的多功能分析仪
这是一个基本的分析器 - 使用 Lucene“服务提供者接口”语法和CustomAnalyzer:
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.custom.CustomAnalyzer;
...
Analyzer analyzer = CustomAnalyzer.builder()
.withTokenizer("icu")
.addTokenFilter("lowercase")
.addTokenFilter("asciiFolding")
.build();
上述分析器使用 Unicode 空白规则对您的输入文本进行标记,编码为 ICU libraries。然后它对小写进行标准化,并映射重音/变音符号/等。到它们的 ASCII 等价物。
使用带状疱疹的示例
如果证明上述方法无法满足您的特定短语匹配需求(即误报得分太高),那么您可以尝试的一种技术是使用带状疱疹作为标记。阅读更多关于带状疱疹的信息here(Elasticsearch 有很好的文档)。
这是一个使用带状疱疹的示例分析器,并使用更“传统”的语法:
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.LowerCaseFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardTokenizer;
import org.apache.lucene.analysis.StopwordAnalyzerBase;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter;
import org.apache.lucene.analysis.shingle.ShingleFilter;
...
StopwordAnalyzerBase.TokenStreamComponents createComponents(String fieldName) {
final Tokenizer source = new StandardTokenizer();
TokenStream tokenStream = source;
tokenStream = new LowerCaseFilter(tokenStream);
tokenStream = new ASCIIFoldingFilter(tokenStream);
// default shingle size is 2:
tokenStream = new ShingleFilter(tokenStream);
return new Analyzer.TokenStreamComponents(source, tokenStream);
}
在此示例中,默认的 shingle 大小为 2(每个 shingle 两个字) - 这是一个很好的起点。
终于...
即使您认为这是一次性练习,以可重复/自动化的方式构建一些 Lucene 索引可能仍然值得费力(这可能需要一段时间,具体取决于您拥有的数据量) .
这样,您可以快速针对索引运行一组已知短语,以查看每个索引的效果。
我故意不说你的最终目标(“计算出现次数”),因为这部分应该相对简单,假设你真的想找到已知短语的完全匹配。可能我误解了您的问题 - 但总的来说,我认为这就是您所需要的。