Improve dsl

This commit is contained in:
Hubert Van De Walle 2020-08-21 16:28:03 +02:00
parent f12947acbd
commit 372652d332
3 changed files with 34 additions and 42 deletions

View File

@ -23,13 +23,9 @@ internal fun PersistedNote.toDocument(): Document {
} }
} }
internal fun TopDocs.toResults(searcher: IndexSearcher) = scoreDocs.map { internal fun Document.toNoteMeta() = PersistedNoteMetadata(
searcher.doc(it.doc).let { doc -> title = get(titleField),
PersistedNoteMetadata( uuid = UuidFieldConverter.fromDoc(get(uuidField)),
title = doc.get(titleField), updatedAt = LocalDateTimeFieldConverter.fromDoc(get(updatedAtField)),
uuid = UuidFieldConverter.fromDoc(doc.get(uuidField)), tags = TagsFieldConverter.fromDoc(get(tagsField))
updatedAt = LocalDateTimeFieldConverter.fromDoc(doc.get(updatedAtField)), )
tags = TagsFieldConverter.fromDoc(doc.get(tagsField))
)
}
}

View File

@ -1,12 +1,14 @@
package be.simplenotes.search package be.simplenotes.search
import org.apache.lucene.document.Document
import org.apache.lucene.index.Term import org.apache.lucene.index.Term
import org.apache.lucene.search.BooleanClause import org.apache.lucene.search.*
import org.apache.lucene.search.BooleanQuery import org.slf4j.LoggerFactory
import org.apache.lucene.search.FuzzyQuery
import org.apache.lucene.search.Query
fun query(receiver: LuceneDsl.() -> Unit): Query { private val logger = LoggerFactory.getLogger("be.simplenotes.search.dsl")
fun IndexSearcher.query(receiver: LuceneDsl.() -> Unit): List<Document> {
val indexSearcher = this
val builder = BooleanQuery.Builder() val builder = BooleanQuery.Builder()
val dsl = LuceneDsl() val dsl = LuceneDsl()
dsl.apply { this.receiver() } dsl.apply { this.receiver() }
@ -15,11 +17,15 @@ fun query(receiver: LuceneDsl.() -> Unit): Query {
builder.add(BooleanClause(FuzzyQuery(Term(field, query)), BooleanClause.Occur.SHOULD)) builder.add(BooleanClause(FuzzyQuery(Term(field, query)), BooleanClause.Occur.SHOULD))
} }
} }
return builder.build() val query = builder.build()
val topDocs = indexSearcher.search(query, dsl.count)
logger.debug("Searching: `$query` results: ${topDocs.totalHits.value}")
return topDocs.scoreDocs.map { indexSearcher.doc(it.doc) }
} }
class LuceneDsl { class LuceneDsl {
val clauses = mutableListOf<BooleanExpression>() val clauses = mutableListOf<BooleanExpression>()
var count: Int = 10
fun addBooleanClause(booleanDsl: BooleanExpression) { fun addBooleanClause(booleanDsl: BooleanExpression) {
clauses.add(booleanDsl) clauses.add(booleanDsl)

View File

@ -1,13 +1,14 @@
package be.simplenotes.search package be.simplenotes.search
import be.simplenotes.domain.model.PersistedNote import be.simplenotes.domain.model.PersistedNote
import be.simplenotes.domain.model.PersistedNoteMetadata
import be.simplenotes.domain.usecases.search.NoteSearcher import be.simplenotes.domain.usecases.search.NoteSearcher
import be.simplenotes.domain.usecases.search.SearchTerms import be.simplenotes.domain.usecases.search.SearchTerms
import be.simplenotes.search.utils.rmdir import be.simplenotes.search.utils.rmdir
import org.apache.lucene.analysis.standard.StandardAnalyzer import org.apache.lucene.analysis.standard.StandardAnalyzer
import org.apache.lucene.document.Document
import org.apache.lucene.index.* import org.apache.lucene.index.*
import org.apache.lucene.search.* import org.apache.lucene.search.IndexSearcher
import org.apache.lucene.search.TermQuery
import org.apache.lucene.store.Directory import org.apache.lucene.store.Directory
import org.apache.lucene.store.FSDirectory import org.apache.lucene.store.FSDirectory
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -26,22 +27,25 @@ class NoteSearcherImpl(basePath: Path = Path.of("/tmp", "lucene")) : NoteSearche
return FSDirectory.open(index) return FSDirectory.open(index)
} }
private fun getIndexSearcher(userId: Int): IndexSearcher { private fun indexSearcher(userId: Int): IndexSearcher {
val directory = getDirectory(userId) val directory = getDirectory(userId)
val reader: IndexReader = DirectoryReader.open(directory) val reader: IndexReader = DirectoryReader.open(directory)
return IndexSearcher(reader) return IndexSearcher(reader)
} }
private fun writer(userId: Int): IndexWriter {
val dir = getDirectory(userId)
val config = IndexWriterConfig(StandardAnalyzer())
return IndexWriter(dir, config)
}
// endregion // endregion
override fun indexNote(userId: Int, note: PersistedNote) { override fun indexNote(userId: Int, note: PersistedNote) {
logger.debug("Indexing note ${note.uuid} for user $userId") logger.debug("Indexing note ${note.uuid} for user $userId")
val dir = getDirectory(userId)
val config = IndexWriterConfig(StandardAnalyzer())
val writer = IndexWriter(dir, config)
val doc = note.toDocument() val doc = note.toDocument()
with(writer) { with(writer(userId)) {
addDocument(doc) addDocument(doc)
commit() commit()
close() close()
@ -51,12 +55,9 @@ class NoteSearcherImpl(basePath: Path = Path.of("/tmp", "lucene")) : NoteSearche
override fun indexNotes(userId: Int, notes: List<PersistedNote>) { override fun indexNotes(userId: Int, notes: List<PersistedNote>) {
logger.debug("Indexing notes for user $userId") logger.debug("Indexing notes for user $userId")
val dir = getDirectory(userId)
val config = IndexWriterConfig(StandardAnalyzer())
val writer = IndexWriter(dir, config)
val docs = notes.map { it.toDocument() } val docs = notes.map { it.toDocument() }
with(writer) { with(writer(userId)) {
addDocuments(docs) addDocuments(docs)
commit() commit()
close() close()
@ -66,11 +67,7 @@ class NoteSearcherImpl(basePath: Path = Path.of("/tmp", "lucene")) : NoteSearche
override fun deleteIndex(userId: Int, uuid: UUID) { override fun deleteIndex(userId: Int, uuid: UUID) {
logger.debug("Deleting index $uuid for user $userId") logger.debug("Deleting index $uuid for user $userId")
val dir = getDirectory(userId) with(writer(userId)) {
val config = IndexWriterConfig(StandardAnalyzer())
val writer = IndexWriter(dir, config)
with(writer) {
deleteDocuments(TermQuery(Term(uuidField, UuidFieldConverter.toDoc(uuid)))) deleteDocuments(TermQuery(Term(uuidField, UuidFieldConverter.toDoc(uuid))))
commit() commit()
close() close()
@ -83,19 +80,12 @@ class NoteSearcherImpl(basePath: Path = Path.of("/tmp", "lucene")) : NoteSearche
indexNote(userId, note) indexNote(userId, note)
} }
override fun search(userId: Int, terms: SearchTerms): List<PersistedNoteMetadata> { override fun search(userId: Int, terms: SearchTerms) =
val searcher = getIndexSearcher(userId) indexSearcher(userId).query {
val query = query {
or { titleField eq terms.title } or { titleField eq terms.title }
or { tagsField eq terms.tag } or { tagsField eq terms.tag }
or { contentField eq terms.content } or { contentField eq terms.content }
} }.map(Document::toNoteMeta)
val topDocs = searcher.search(query, 10)
logger.debug("Searching: `$query` results: ${topDocs.totalHits.value}")
return topDocs.toResults(searcher)
}
override fun dropIndex(userId: Int) = rmdir(File(baseFile, userId.toString()).toPath()) override fun dropIndex(userId: Int) = rmdir(File(baseFile, userId.toString()).toPath())