lucille
Lucille is a small library for parsing and representing queries using the Lucene query syntax.
Usage
This library is currently available for Scala binary versions 2.12, 2.13, and 3.
Additionally, it's available for the JVM, Scala.js, and Scala Native.
To use the latest version, include the following in your build.sbt
:
// use this snippet for the JVM
libraryDependencies += "pink.cozydev" %% "lucille" % "0.0.2"
// use this snippet for JS, Native, or cross-building
libraryDependencies += "pink.cozydev" %%% "lucille" % "0.0.2"
Parsing
Lucille offers a parse
function to parse a whole string into a Lucille MultiQuery
structure:
import pink.cozydev.lucille.QueryParser
QueryParser.parse("cats OR dogs")
// res0: Either[String, pink.cozydev.lucille.MultiQuery] = Right(
// value = MultiQuery(
// qs = NonEmptyList(
// head = Or(
// qs = NonEmptyList(
// head = Term(str = "cats"),
// tail = List(Term(str = "dogs"))
// )
// ),
// tail = List()
// )
// )
// )
Last Query Rewriting
To enable a better interactive search experience, it can be helpful to rewrite the last term as a prefix term to enable partial matching on terms.
We'll write a helper function expandQ
to rewrite Term
queries into a query that matches either
that term OR
a Prefix
query:
import pink.cozydev.lucille.Query
def expandQ(q: Query): Query =
q match {
case Query.Term(t) => Query.Or(Query.Term(t), Query.Prefix(t))
case _ => q
}
We can now use expandQ
along with mapLastTerm
to rewrite the last term of a MultiQuery
into our
expanded term + prefix:
QueryParser.parse("cats meo").map(mq => mq.mapLastTerm(expandQ))
// res1: Either[String, pink.cozydev.lucille.MultiQuery] = Right(
// value = MultiQuery(
// qs = NonEmptyList(
// head = Term(str = "cats"),
// tail = List(
// Or(
// qs = NonEmptyList(
// head = Term(str = "meo"),
// tail = List(Prefix(str = "meo"))
// )
// )
// )
// )
// )
// )
This also works when the last term is part of a boolean or field query.
QueryParser.parse("cats AND do").map(mq => mq.mapLastTerm(expandQ))
// res2: Either[String, pink.cozydev.lucille.MultiQuery] = Right(
// value = MultiQuery(
// qs = NonEmptyList(
// head = And(
// qs = NonEmptyList(
// head = Term(str = "cats"),
// tail = List(
// Or(
// qs = NonEmptyList(
// head = Term(str = "do"),
// tail = List(Prefix(str = "do"))
// )
// )
// )
// )
// ),
// tail = List()
// )
// )
// )