Installation
# Gemfilegem 'esse'gem 'esse-jbuilder'Loading the gem prepends Jbuilder-aware behavior to Esse::Search::Query.
Inline Jbuilder
Pass a block to any search call and the block becomes the search body:
query = UsersIndex.search do |json| json.query do json.match do json.set! 'name', params[:q] end endend
query.response.resultsFor complex queries, Jbuilder’s DSL is often easier than nested hashes:
UsersIndex.search do |json| json.query do json.bool do json.must do json.child! do json.match { json.set! 'name', params[:q] } end end if (states = params[:state_abbr]) json.filter do json.child! do json.terms { json.set! 'state_abbr', states } end end end end end
json.aggs do json.states do json.terms { json.set! 'field', 'state_abbr' } end endendMultiple indices work the same way:
Esse.cluster.search(CitiesIndex, CountiesIndex) do |json| json.query do json.match_all endendTemplate files
Set the template directory (default app/searches):
Esse.configure do |config| config.search_view_path = 'app/searches'endCreate app/searches/cities/search.json.jbuilder:
json.query do json.match do json.set! 'name', @name endendRender it:
body = Esse::Jbuilder::Template.call('cities/search', name: 'Chicago')CitiesIndex.search(body: body)Rails view templates
Esse::Jbuilder::ViewTemplate uses Rails’ ActionView lookup so you can include partials and share them with normal Rails views:
json.query do json.match do json.set! 'name', @name endendjson.partial! 'shared/pagination', page: @pagebody = Esse::Jbuilder::ViewTemplate.call('cities/search', name: params[:q], page: params[:page])CitiesIndex.search(body: body)ViewTemplate must be called in a Rails process (needs ActionView). It uses your app’s full view lookup context, including partials and helpers.
Symbol keys
By default ViewTemplate returns string-keyed hashes. Opt into symbols globally:
Esse::Jbuilder::ViewTemplate.symbolize_keys = trueSearcher pattern
A tidy pattern for non-trivial queries:
class Searchers::CitiesSearcher extend Forwardable def_delegators :search, :response, :results
def initialize(params) @params = params.symbolize_keys end
def call search end
private
def search @search ||= CitiesIndex .search(body: body) .limit(@params.fetch(:limit, 10)) .offset(@params.fetch(:offset, 0)) end
def body Esse::Jbuilder::ViewTemplate.call('cities/search', **@params) endend
Searchers::CitiesSearcher.new(params).call.resultsTips
- Jbuilder’s
json.set!avoids method-name collisions with Ruby keywords or symbols ES expects (match_all,terms, etc.). - Use
json.child!to build arrays insidemust,filter,should, etc. - Helpers defined in
ApplicationHelperare available insideViewTemplatebecause it uses the standard Rails view context.