Я использую Lucene для получения частоты терминов в документах, то есть количества вхождений какого-либо термина в каждом документе. Я использую IndexReader.termDocs()
для этой цели, и он отлично работает для однословных терминов, но, поскольку все слова хранятся в индексе отдельно, он не работает для многословных терминов.
Пример (взято из этого вопроса): меня интересует частота термина "баскетбол" (или даже "баскетбол"), но после токенизации будет быть двумя словами, и я смогу получить частоту термина «корзина» и термин «мяч», но не термин «баскетбол».
Я знаю все термины из нескольких слов, для которых я хочу получать частоту, также я не заинтересован в сохранении исходного текста - только в получении статистики. Итак, мой первый подход заключался в том, чтобы просто объединить слова в термине . Например. «Я играл баскетбол вчера» становится «Я играл баскетбол вчера», а «Мой любимый писатель Курт Воннегут » становится «Мой любимый писатель Воннегут ». Это работает: объединенные термины обрабатываются как любое другое отдельное слово, поэтому я могу легко получить частоту. Но этот метод уродлив и, что более важно, очень медленный. Итак, я пришел к другому.
Мой второй подход заключается в написании специального токен-фильтра , который будет захватывать токены и проверять, являются ли они частью заменяемых терминов (что-то вроде SynonymFilter
из Lucene в действии ). В нашем случае, когда фильтр увидит слово «корзина», он будет читать еще один токен, а если это «шарик», фильтр поместит один термин («баскетбол») вместо двух («корзина» и «шар») в поток токенов вывода. Преимущество этого метода по сравнению с предыдущим заключается в том, что он ищет совпадения между полными словами и не сканирует полный текст на наличие подстрок. На самом деле, большинство токенов будут иметь разную длину и поэтому будут отбрасываться, даже не проверяя соответствие любой буквы в них. Но такой фильтр написать нелегко, более того, я не уверен, что он будет достаточно быстрым, чтобы соответствовать моим потребностям.
Третий подход, о котором я могу подумать, это поиграть с позициями двух слов в одних и тех же документах. Но, скорее всего, это будет включать в себя итерацию TermDocs
во время получения частоты, которая стоит намного больше, чем время индексации.
Итак, наконец, мой вопрос: Есть ли способ эффективно индексировать и получать частоту многословных терминов в Lucene?