95 lines
2.9 KiB
Kotlin
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())
|
|
|
|
}
|