Поможет ли индекс Lucene ускорить подсчет случаев? - PullRequest
0 голосов
/ 10 февраля 2020

У меня большой текстовый файл, из которого я хочу сосчитать вхождения известных фраз. В настоящее время я построчно читаю весь текстовый файл в память и использую функцию «найти», чтобы проверить, существует ли конкретная фраза в текстовом файле:

found = txt.find(phrase) 

Это очень медленно для большого файла. Построить указатель всех возможных фраз и сохранить их в комментариях поможет, но проблема в том, чтобы создать все значимые фразы самостоятельно. Я знаю, что поисковая система Lucene поддерживает поиск по фразе. При использовании Lucene для создания индекса для текстового набора, мне нужно придумать свой собственный метод токенизации, особенно для цели поиска моих фраз выше? Или у Lucene есть эффективный способ автоматического создания индекса для всех возможных фраз, и мне не нужно беспокоиться о том, как создавать фразы?

Моя главная цель - найти хороший способ подсчета случаев в большом тексте.

1 Ответ

1 голос
/ 12 февраля 2020

Резюме: Lucene позаботится о том, чтобы присвоить индексированному тексту более высокие показатели соответствия, которые более точно соответствуют вашим входным фразам, без необходимости «создавать все значимые фразы» самостоятельно.

Начните с простого

Я рекомендую начать с базового c анализатора Lucene и посмотреть, какой эффект это даст. Существует достаточно хороший шанс, что он удовлетворит ваши потребности.

Если это не даст вам удовлетворительных результатов, то вы, безусловно, можете исследовать более конкретные / целевые анализаторы / токенизаторы / фильтры (например, если вам нужно проанализировать нелатинские наборы символов).

Трудно быть более точным c, не глядя на исходные данные и требования соответствия фраз более подробно.

Но, сказав это, Вот два примера (и я предполагаю, что у вас есть базовые знания о том, как создать индекс Lucene и затем запросить его).

Весь код основан на Lucene 8.4.

CAVEAT - я не знаком с Python реализациями Lucene. Итак, с извинениями мои примеры приведены в Java - не Python (так как ваш вопрос помечен). Я полагаю, что понятия несколько переводимы. Приносим извинения за то, что это для вас.

Многоцелевой анализатор Basi c

Вот анализатор basi c - с использованием поставщика услуг 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 . Затем он стандартизируется в нижнем регистре и отображает акценты / диакритические знаки / et c. к их ASCII-эквивалентам.

Пример с использованием опоясывающего лишая

Если вышеуказанный подход окажется слабым для ваших конкретных c потребностей соответствия фраз (то есть ложных срабатываний, набравших слишком высокий балл), тогда один метод вы можете попробовать использовать дранку в качестве жетонов. Подробнее о черепице здесь (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);
}

В этом примере по умолчанию размер гальки равен 2 (два слова на гальку) - это хорошее место для начала.

Наконец ...

Даже если вы думаете, что это одно- Временное упражнение, вероятно, все еще стоит потрудиться, чтобы создать некоторые индексы Lucene повторяемым / автоматическим способом (который может занять некоторое время в зависимости от количества данных, которые у вас есть).

Таким образом, будет очень быстро запустить ваш набор известных фраз для индекса, чтобы увидеть, насколько эффективен каждый индекс.

Я специально ничего не сказал о вашей конечной цели (" для подсчета вхождений "), потому что эта часть должна быть относительно простой, если вы действительно хотите найти точные совпадения для известных фраз. Возможно, я неправильно истолковал ваш вопрос - но на высоком уровне я думаю, что это то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...