【问题标题】:Will Lucene index help speed up to count occurrence?Lucene 索引是否有助于加快计数发生的速度?
【发布时间】:2020-02-10 18:09:46
【问题描述】:

我有一个大文本文件,我想从中计算已知短语的出现次数。我目前将整个文本文件逐行读取到内存中,并使用“查找”功能检查文本文件中是否存在特定短语:

found = txt.find(phrase) 

这对于大文件来说非常慢。建立所有可能短语的索引并将它们存储在 dict 中会有所帮助,但问题是自己创建所有有意义的短语具有挑战性。我知道 Lucene 搜索引擎支持词组搜索。在使用 Lucene 为文本集创建索引时,我是否需要提出自己的标记化方法,尤其是用于上述短语搜索的目的?或者 Lucene 有一种有效的方法来自动为所有可能的短语创建索引,而无需我担心如何创建短语?

我的主要目的是找到一种计算大文本中出现次数的好方法。

【问题讨论】:

    标签: python lucene


    【解决方案1】:

    总结: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 索引可能仍然值得费力(这可能需要一段时间,具体取决于您拥有的数据量) .

    这样,您可以快速针对索引运行一组已知短语,以查看每个索引的效果。

    我故意不说你的最终目标(“计算出现次数”),因为这部分应该相对简单,假设你真的想找到已知短语的完全匹配。可能我误解了您的问题 - 但总的来说,我认为这就是您所需要的。

    【讨论】:

      猜你喜欢
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 2023-01-05
      • 2010-09-10
      • 2016-03-31
      • 2022-01-25
      • 2015-08-29
      相关资源
      最近更新 更多