Scopes

The Flex::Scopes module is included in your Flex::ActiveModel models, so you can just use them without the include Flex::ActiveModel statement. On the other hand, you can include the Flex::Scopes with any class that includes any Flex module, and with a simple trick, also with your ActiveRecord models (that defines their own scope method) (see Using flex-scopes with ActiveRecord Models) .

Filter Scopes

The flex-scope gems implements only a few of the most commonly used elasticsearch filters, plus a generic filters scope that allows to add any other filter not explicitly defined as a scope. All the Filter Scopes return a Flex::Scope object.

missing

elasticsearch missing-filter API

Accepts a single key hash or a multiple keys hash (that will be translated in a sequence of term calls)

missing(:color).missing(:category)
# or
missing(:color, :category)
term

elasticsearch term-filter API

Accepts a single key hash or a multiple keys hash (that will be translated in a sequence of term calls)

term(:color => 'red').term(:category => 'new')
# or simply
term(:color => 'red', :category => 'new')
terms

An extended version of the elasticsearch terms-filter API

In its basic usage it conforms to the API, but it allows also to represent the term and the missing scopes, internally translating them in a serie of multiple scopes:

# basic usage as in the API
terms(:color => ['red', 'blue'], :category => ['new', 'used'])
# if you pass a single value instead of an array it behaves exactly like `term`
terms(:color => 'red')
# if you pass a nil value it behaves exactly like `missing`
terms(:color => nil)
# all together
terms(:color => 'red', :category => ['new', 'used'], :code => nil)
# is like
term(:color => 'red').terms(:category => ['new', 'used']).missing(:code)
range

Implements the elasticsearch range-filter

range(:date => { :from => '2013-04-01',
                 :to   => '2013-04-30' } )
filters

This scope is a generic scope that allows to add any elasticsearch filter structure not explicitly available as a scope.

Accepts a single, or an array, or a list of filter structures. For example:

filters(:numeric_range => { :age => { :from => 10,
                                      :to   => 20,
                                      :include_lower => true,
                                      :include_upper => false } )
and and or wrappers

You can wrap groups of filters in and or or blocks (eventually nested) and they will be built into a final elasticsearch filter.

YourClass.or{ term(:color => 'red').term(:category => 'new') }

If you omit the wrapper for the filter scopes the and wrapper will be used

Variable Scopes

These scopes are a direct interface for the variables used to query. All the Variable Scopes return a Flex::Scope object.

query_string

This scope accepts a query string or an hash to parse as documented in elasticsearch query-string-query API. If omitted it uses {'query': '*'} as the default (i.e. sort of match_all query). It passes it as a cleanable_query for easier handling (see :cleanable_query)

query_string('title:{Aida TO Carmen}')
# or
query_string( :query  => 'title:{Aida TO Carmen}',
              :fields => ['text', 'category'] )

See Lucene Query Parser Syntax

Notice: the query_string scope gets overriden by chaining with another query_string scope

query

Alias for query_string

sort

This scope accepts one or an array or a list of sort structures documented as elasticsearch sort API.

sort(:name => 'asc')
fields

The fields that you want to retrieve in order to limit the size of the response

# pass an array of fields
fields([:field_one, :field_two])
# or a list of fields
fields(:field_one, :field_two)

a fields scope used on Flex::ActiveModel models, freezes the returned objects (i.e. make them not editable)

script_fields

Implements the elasticsearch script-fields API. Adds one or more script fields to the scope.

script_fields( :my_field       => 'script ...',                    # simpler form
               :my_other_field => {:script => 'script ...', ...} ) # elasticsearch API
size

Limits the size of the retrieved hits

size(5)
# same effect of
params(:size => 5)
page

The page of the pagination. By setting this scope you get automatically set the :from param, consistently with the :size (that is usually defaulted). Very convenient when you get the page number from a pagination link). Default 1.

page(3)

This scope is a direct interface to the :page special variable (see :page)

params

The params are a hash of key/value pairs. Flex will transform them in the query string part of the path (all what comes after the ?).

params(:size => 4)

This scope is a direct interface to the :params special variable (see :params)

index

The :index predefined variable

index('my_index')
index(['my_index', 'my_other_index'])

This scope is a direct interface to the :index predefined variable (see :index)

type

The :type predefined variable

type('my_type')
type(['my_type', 'my_other_type'])

This scope is a direct interface to the :type predefined variable (see :type)

variables

A generic scope usable to add variables

# returns the same scope
variables
# injects new variables
variables(a_hash, another_hash, :a => 2, :b => 4)
facets

Implements a generic elasticsearch facets API usable with all the facets (just pass the facet hash structure).

facets(:tags => {:term => {:field => 'tags'}})
highlights

Implements the elasticsearch highlighting API.

highlight(:fields => {:text => {}})
metrics

Adds the elasticsearch search_type API of type count. Useful when you need to query only the counts and not the actual results.

count_result = any_scope.metrics.all
# is like
count_result = any_scope.params(:search_type => 'count').all

Query Scopes

All the Query Scopes methods actually perform the query generated by the scope and return some kind of result but not a scope object, so they are used as the last scope in the chain. They all accept a list of variables (which will be deep-merged with the variables contained in the scope itself).

If they are called on your class directly, they first generate an empty scope without restrictions, internally using the scoped method (see scoped). Depending on the method, the result may be a single document, a collection of documents, or the actual instance(s) of your class when used with Flex::ActiveModel models. Others allow you to count or iterate over some retrieved collection.

find

Retrieves a single or multiple documents using their ids

# pass a single id
find '1Momf4s0QViv-yc7wjaDCA'
# or an array of ids
find ['1Momf4s0QViv-yc7wjaDCA', 'BFdIETdNQv-CuCxG_y2r8g']
first

Retrieves the first document of the scope

red_scope.first
MyFlexActiveModel.first
last

Retrieves the last document of the scope

red_scope.last
MyFlexActiveModel.last
all

Retrieves all the documents of the scope

red_scope.all
MyFlexActiveModel.all
delete

Deletes the documents of the scope

red_scope.delete
# deletes all the documents
MyFlexActiveModel.delete
each

Iterates over all the documents in the scope

red_scope.each{|d| do_something_with(d)}
MyFlexActiveModel.each{|d| do_something_with(d)}
scan_all

Iterates in batches, over all the documents in the scope by using the elasticsearch search_type API of type scan

red_scope.scan_all do |batch|
  batch.each {|d| do_something_with(d)}
end

 MyFlexActiveModel.scan_all do |batch|
   batch.each {|d| do_something_with(d)}
 end
each_batch, find_in_batches

Aliases for scan_all

count

Counts the documents in the scope

red_scope.count
MyFlexActiveModel.count

Methods

scoped

This method creates a new Flex::Scope object, containing only the :context variable (i.e. your class/module). It is automatically used by all the scopes methods called directly on your class, so you probably will never need to use it directly.

scope

This method generates a named scope in your class. It requires a symbol name as the first argument, and a scope, or a block (or Proc) returning a scope, as the second argument.

# scope object
scope :red, term(:color => 'red')
# block
scope :color do |color|
  term(:color => color).sort(:category => 'asc')
end
# proc
scope :a_scope, a_proc
scope_methods

The array of all the named scopes you defined. Mostly used internally.

method_missing

Used to chain the scopes with other scopes, or eventually with templates defined by Flex::Templates.

# specially useful with variable scopes
scope :my_variables, size(5).fields(:field_one, :field_two)

# you can call a template on any scope
my_variables.my_template_name

# which is like
YourClass.my_template_name(my_variables)

Using flex-scopes with ActiveRecord Models

You must not include Flex::Scopes right in your ActiveRecord models: instead you should namespace your scopes and set the context to your model. For example:

class MyModel < ActiveRecord::Base
  include Flex::ModelIndexer

  module Flex
    include Flex::Scopes
    flex.context = MyModel
    scope :red, terms(:color => 'red')
    ...
  end

end

total_red = MyModel::Flex.red.count
first_red = MyModel::Flex.red.first

Notice: When you namespace the scopes, you must set the flex.context with your model class.