eson-dsl: The elasticsearch query DSL, in Ruby
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
require 'eson-dsl'
require 'json'
q = Eson::Search::BaseQuery.new do
query do
wildcard :user, :value => "kim*y", :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:
{
"query": {
"wildcard": {
"user": {
"value": "kim*y",
"boost": 2.0}
}
}
},
"filter": {
"range": {
"age": {
"from": 10,
"to": 20
}
}
},
"facets": {
"hist1": {
"histogram": {
"field": "age",
"interval": 2
}
}
}
}
For a list of all available generation methods along with examples, have a look at MethodReference.
Parameters
Parameters can be passed to BaseQuery to allow generation of dynamic queries, without playing with variable visibility:
Eson::Search::BaseQuery.new(:search_string => "kim*y", :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:
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:
q.filter do |f|
f.or do
term "name.first" => "Felix"
term "name.first" => "Florian"
end
end
and
q.filter do |f|
f.and do #and is a keyword, so it needs a receiver
range :post_date, {:from => "2010-03-01", :to => "2010-04-01"}
prefix "name.second" => "ba"
end
end
Due to clever defaults, and
can be omitted altogether:
q.filter do |f|
range :post_date, {:from => "2010-03-01", :to => "2010-04-01"}
prefix "name.second" => "ba"
end