SimpleNotes/search/src/main/kotlin/NoteSearcherImpl.kt
2020-08-21 16:28:03 +02:00

95 lines
2.9 KiB
Kotlin

package be.simplenotes.search
import be.simplenotes.domain.model.PersistedNote
import be.simplenotes.domain.usecases.search.NoteSearcher
import be.simplenotes.domain.usecases.search.SearchTerms
import be.simplenotes.search.utils.rmdir
import org.apache.lucene.analysis.standard.StandardAnalyzer
import org.apache.lucene.document.Document
import org.apache.lucene.index.*
import org.apache.lucene.search.IndexSearcher
import org.apache.lucene.search.TermQuery
import org.apache.lucene.store.Directory
import org.apache.lucene.store.FSDirectory
import org.slf4j.LoggerFactory
import java.io.File
import java.nio.file.Path
import java.util.*
class NoteSearcherImpl(basePath: Path = Path.of("/tmp", "lucene")) : NoteSearcher {
private val baseFile = basePath.toFile()
private val logger = LoggerFactory.getLogger(javaClass)
// region utils
private fun getDirectory(userId: Int): Directory {
val index = File(baseFile, userId.toString()).toPath()
return FSDirectory.open(index)
}
private fun indexSearcher(userId: Int): IndexSearcher {
val directory = getDirectory(userId)
val reader: IndexReader = DirectoryReader.open(directory)
return IndexSearcher(reader)
}
private fun writer(userId: Int): IndexWriter {
val dir = getDirectory(userId)
val config = IndexWriterConfig(StandardAnalyzer())
return IndexWriter(dir, config)
}
// endregion
override fun indexNote(userId: Int, note: PersistedNote) {
logger.debug("Indexing note ${note.uuid} for user $userId")
val doc = note.toDocument()
with(writer(userId)) {
addDocument(doc)
commit()
close()
}
}
override fun indexNotes(userId: Int, notes: List<PersistedNote>) {
logger.debug("Indexing notes for user $userId")
val docs = notes.map { it.toDocument() }
with(writer(userId)) {
addDocuments(docs)
commit()
close()
}
}
override fun deleteIndex(userId: Int, uuid: UUID) {
logger.debug("Deleting index $uuid for user $userId")
with(writer(userId)) {
deleteDocuments(TermQuery(Term(uuidField, UuidFieldConverter.toDoc(uuid))))
commit()
close()
}
}
override fun updateIndex(userId: Int, note: PersistedNote) {
logger.debug("Updating note ${note.uuid} for user $userId")
deleteIndex(userId, note.uuid)
indexNote(userId, note)
}
override fun search(userId: Int, terms: SearchTerms) =
indexSearcher(userId).query {
or { titleField eq terms.title }
or { tagsField eq terms.tag }
or { contentField eq terms.content }
}.map(Document::toNoteMeta)
override fun dropIndex(userId: Int) = rmdir(File(baseFile, userId.toString()).toPath())
override fun dropAll() = rmdir(baseFile.toPath())
}