Я создал индекс с помощью Lucene для 130 миллионов текстов по 300 символов в каждом.
вот как я использую этот индекс:
import org.apache.lucene.analysis.core.WhitespaceAnalyzer
import org.apache.lucene.index.DirectoryReader
import org.apache.lucene.search.BooleanClause
import org.apache.lucene.search.BooleanQuery
import org.apache.lucene.search.IndexSearcher
import org.apache.lucene.search.MatchAllDocsQuery
import org.apache.lucene.store.NIOFSDirectory
import org.apache.lucene.util.QueryBuilder
import java.nio.file.Path
class LuceneNegativesIndex(val indexFolderPath: Path) : NegativesIndex {
val standardAnalyzer = WhitespaceAnalyzer()
var directory = NIOFSDirectory.open(indexFolderPath)
val reader = DirectoryReader.open(directory)
val queryBuilder = QueryBuilder(standardAnalyzer)
val searcher = IndexSearcher(reader)
val allDocsQuery = MatchAllDocsQuery()
override fun count(phrase: String, mustNot: List<String>): Long {
val booleanQueryBuilder = BooleanQuery.Builder()
val phraseQ = queryBuilder.createPhraseQuery("content", phrase)
booleanQueryBuilder.add(phraseQ, BooleanClause.Occur.MUST)
mustNot.forEach {
val q = queryBuilder.createPhraseQuery("content", it)
booleanQueryBuilder.add(q, BooleanClause.Occur.MUST_NOT)
}
val results = searcher.search(booleanQueryBuilder.build(), 1)
return results.totalHits
}
}
чтобы упростить его, я объясню:
Я пытаюсь извлечь все тексты, которые содержат конкретное слово, а также не содержат любое слово изне должен список слов.и узнать, сколько таких текстов я получил в своем индексе
. Проблема, с которой я сталкиваюсь, заключается в том, что после создания списка mustNot он остается таким же , и только фраза, которую я хочу найти втексты меняются.
после профилирования времени выполнения я обнаружил, что эта функция составляет 43% от всего процессорного времени
, и вот как я ее использую
fun getAllNegCount(): HashMap<String,Int>{
val kp2negCount = HashMap<String,Int>()
val searcher = LuceneNegativesIndex(PATH_TO_INDEX)
val mustNot = selectBlackList() //size uselly between 10-20 detrmine in run time
val keyPhrases = getAllKP()//size uselly between 2000-3000 detrmine in run time
keyPhrases.forEach{kp->
kp2negCount[kp]= searcher.search(kp,mustNot)
}
return kp2negCount
}
если это была рациональная база данных SQL, я, вероятно, сначала получал все тексты, которые не содержали никаких слов из списка mustNot , и в этом наборе текста просто искал тексты, содержащие фразу.
но вместо этого мне нужно каждый раз запускать весь запрос по всему индексу.
Я не мог найти способ выполнить поиск по найденным документам.
любые идеи или другиеподходы к решению этой проблемы?
или способ оптимизации этого запроса?
или, возможно, использование Lucene - не лучшее решение для этого варианта использования?