48 lines
1.4 KiB
Kotlin

package be.simplenotes.search
import org.apache.lucene.document.Document
import org.apache.lucene.index.Term
import org.apache.lucene.search.*
import org.slf4j.LoggerFactory
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 dsl = LuceneDsl()
dsl.apply { this.receiver() }
dsl.clauses.forEach { (field, query) ->
query?.let {
builder.add(BooleanClause(FuzzyQuery(Term(field, query)), BooleanClause.Occur.SHOULD))
}
}
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 {
val clauses = mutableListOf<BooleanExpression>()
var count: Int = 10
fun addBooleanClause(booleanDsl: BooleanExpression) {
clauses.add(booleanDsl)
}
infix fun List<String>.anyMatch(query: String?) {
map { BooleanExpression(it, query) }.forEach {
addBooleanClause(it)
}
}
}
fun LuceneDsl.or(booleanExpression: () -> BooleanExpression) {
addBooleanClause(booleanExpression())
}
infix fun String.eq(query: String?) = BooleanExpression(this, query)
data class BooleanExpression(val term: String, val query: String?)