eson-dsl: The elasticsearch query DSL, in Ruby

Build Status

This gem provides a full implementation of the ElasticSearch query DSL, independent of a client. At the moment, it encodes the query DSL of ElasticSearch 0.19

Features:

  • Safe: it does its best to avoid generating improper queries
  • Close to the original: All queries and filters have the same name an similar parameter order as in the elasticsearch documentation
  • Ease of use: makes handing some of the trickier aspects of the query language easier
  • Complete: Incorporates all of the elasticsearch query language

Usage

“uby require ‘eson-dsl’ require ‘json’

q = Eson::Search::BaseQuery.new do query do wildcard :user, :value => “kimy“, :boost => 2.0 end filters do range :age, :from => 10, :to => 20 end facets do histogram :hist1, :field => :age, :interval => 2 end end

JSON.dump(q.to_query_hash)

This example yields:

“on { “query”: { “filtered”: { “query”: { “wildcard”: { “user”: { “value”: “kimy“, ”boost“: 2.0} } } }, ”filter“: { ”range“: { ”age“: { ”from“: 10, ”to“: 20 } } } } }, ”facets“: { ”hist1“: { ”histogram“: { ”field“: ”age“, ”interval“: 2 } } } }

The query generator does its best to avoid extra work. For example, if filtering is all you want, you can omit the query part - a filtered query with a match_all-query will be generated automatically:

“by q.filter do term “foo”, :value => ‘bar’ end

will generate:

“by { “query”: { “filtered”: { “query”: { “match_all”: { } }, “filter”: { “term”: { “foo”: { “value”: “bar” } } } } } }

Parameters

Parameters can be passed to BaseQuery to allow generation of dynamic queries, without playing with variable visibility:

“by Eson::Search::BaseQuery.new(:search_string => “kimy“, :boost => 2.0) do query do wildcard :user, :value => param(:search_string), :boost => param(:boost) end end

Examples

See examples for all examples used in the test suite.

Specialities

Eson supports scoped facets in an object-oriented way. To scope a facet, call scope on it and pass the reference to a subquery. In practice, this requires a bit of trickery in Ruby 1.9, as it local variables are not propagated outside of the introducing block:

“by Eson::Search::BaseQuery.new do q = nil query do q = nested :path => :obj1, :score_mode => “avg” do query do match_all end filters do range :age, :from => 10, :to => 20 end end end

facets do (histogram :hist1, :field => :age, :interval => 2).scope(q, ‘my_scope’) end end

Caveats

and, not and or are Ruby keywords and can only be used as methods of the receiver is explicit. For that reason, you need to write the following to generate and- and or-filters:

“by q.filter do |f| f.or do term “name.first” => “Felix” term “name.first” => “Florian” end end

and

“by q.filter do |f| f.and do #and is a keyword, so it needs a receiver range :post_date, prefix “name.second” => “ba” end end

Due to clever defaults, and can be omitted altogether:

“by q.filter do |f| range :post_date, prefix “name.second” => “ba” end

TODO

  • Indices-Query is missing
  • Custom-Boost-Query is missing)
  • More docs
  • Testing on Ruby 1.8