48 lines
1.4 KiB
Kotlin
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?)
|