Elasticquery

Gem Version Build Status Code Climate Test Coverage

A module for elasticsearch-rails libraries like as user-friendly query generator.

Instalation

To install using Bundler grab the latest stable version:

gem 'elasticquery'

To manually install elasticquery via Rubygems simply gem install:

gem install elasticquery

Getting Started

First instruction

Elasticquery was designed to be customized as you need to. Providing simple methods it allows you to build flexible queries using Elastic Query DSL

class MyQuery < Elasticquery::Base
  filtered do |params|
    filters do
      term "user.id" => params[:user_id]
      range.not :age, gte: 18
    end
    queries do
      multi_match params[:query]
    end
  end
end
query = MyQuery.new query: 'i typed', user_id: 5
query.build # => query for elastic
Article.search query.build # => returns result 

Currently you have

Filters

Term

  # Simple one term filter
  term category: 'Rock'

  # _cache option support
  term category: 'Soul', _cache: false

  # Blank values are skipped. This query returns all records
  term name: " "

Terms

  # Standard terms options
  terms a: 1, b: 2

  # Skip empty values
  terms a: 1, b: "" # => {a: 1} wil be passed

  # Blank terms are skipped
  terms a: "", b: nil # => match_all will be executed

  # _cache and execution support
  terms a: 1, b: 2, _cache: false, execution: "or"

  # where alias. Usable in chain calls
  where a: 1, b: 2, c: 3

Range

  # One side range
  range :age, gte: 18

  # Double sides range
  range :volume, gte: 1, lte: 100

  # _cache and execution options support
  range :volume, gte: 1, lte: 100, _cache: true, execution: "fielddata"

Exists Missing

  # Field existence check
  exists "last_name"
  missing "last_name"

  # Blank value skipped
  exists ""
  missing ""

  # Has with alias
  with 'first_name'
  without 'first_name'

Not

  # Blank values are skipped. This query returns all records
  range.not :age, lte: ' ', gte: nil

  # Term exclusion
  term.not category: 'Rap'

  # Terms exclusion
  terms.not category: 'Rap', name: "Guf"

  # 'Exists not' uses missing
  with.not #=> returns missing filter

All filters are joined by AND filter.

Queries

MultiMatch

  # Simple all fields search in your index
  multi_match 'developers'

  # The same as above
  multi_match 'developers', fields: "_all", operator: "and", type: "best_fields"

  # Configure fields
  multi_match 'Jordan', fields: ['first_name', 'last_name'], operator: "or"

  # Blank values are skipped. This query returns all records
  multi_match ''

  # Alias as search
  search 'Hello!'

Extended instruction

There are multiple ways to organize your query, using chaining calls, or custom filters.

  • Chain calls

    PeopleQuery.new.queries.multi_match('hi', operator: :or).filters.term(age: 21).build # => returns hash
    Query.new.queries./queries-chain/.filters./filters-chain/
    
  • Class methods

class PeopleQuery < Elasticquery::Base
  filtered do |params|
    filters do
      range :age, lte: prepare_age(params[:max_age])
    end
  end

  protected

  def prepare_age(param)
    param.to_i
  end
end
PeopleQuery.build(max_age: '42') # => result
  • Multiple filtered blocks
class ChildQuery < Elasticquery::Base
  filtered do |params|
    filters do
      term :'category.id' => params[:category_id]
    end
  end

  filtered do |params|
    filters do
      term :'author.id' => User.find(params[:user_id]).name
    end
  end
end
ChildQuery.build({user_id: 1, category_id: 14}) => returns both user and category filters
  • Query inheritance
class ParentQuery < Elasticquery::Base
  filtered do |params|
    filters do
      term :'category.id' => params[:category_id]
    end
  end
end

class ChildQuery < ParentQuery
  filtered do |params|
    filters do
      term :'author.id' => User.find(params[:user_id]).name
    end
  end
end

ChildQuery.build({user_id: 1, category_id: 14}) => # the same as in previous example
  • Elasticsearch::Model support with es shortcut
class Article
  include Elasticsearch::Model
  extend Elasticquery::Es
end

Article.es.filters.term(user_id: 12).with("published_at").queries.search("Verge").results # => collection of "hits"
Article.es.filters.term(user_id: 12).with("published_at").queries.search("Verge").records # => collection of records from db