1

I would like to build a dynamic query in with elastic4s.

I have a request object called myRequest with two fileds (fieldA and fieldB)

Actually i build my query like this :

val req =
      search in indexName -> indexType query {
        bool {
          should(
            matchQuery("fieldA", myRequest.fieldA.getOrElse("")),
            matchQuery("fieldB", myRequest.fieldA.getOrElse("")),

          )
        }
      }

But What I d like to have is : when the fieldA is empty no matchQuery will be added to my query

Thanks for your help

hbellahc.

hbellahc
  • 81
  • 1
  • 11

1 Answers1

5

You can construct a list with all your subqueries using flatten. This is a super verbose code to illustrate:

val fieldA: Option[String] = ...
val fieldB: Option[String] = ...
val shouldA: Option[QueryDefinition] = fieldA.map(a => matchQuery("fieldA", a))
val shouldB: Option[QueryDefinition] = fieldB.map(b => matchQuery("fieldB", b))
val req =
  search in indexName -> indexType query {
    bool {
      should(Seq(shouldA, shouldB).flatten: _*)
    }
  }

Note the _* type annotation: it is required to unpack the list of arguments. Generally speaking, whenever you call a method that has variable-length list of parameters, each of type T, you can take a Seq[T] and unpack it using : T*. For convenience, you might say _* instead and the compiler will infer the type for you.

So, the concise way:

def search(maybeA: Option[String], maybeB: Option[String]) = 
  search in indexName -> indexType query {
    bool {
      should(
        Seq(
          maybeA.map(a => matchQuery("fieldA", a),
          maybeB.map(b => matchQuery("fieldB", b)
        ).flatten: _*
      )
    }
  }
Wojciech Ptak
  • 683
  • 4
  • 14