module Chewy::Index::Mapping::ClassMethods

Public Instance Methods

agg(name, &block) click to toggle source

Defines an aggregation that can be bound to a query or filter

@example

# Suppose that a user has posts and each post has ratings
# avg_post_rating is the mean of all ratings
class UsersIndex < Chewy::Index
  index_scope User
  field :posts do
    field :rating
  end

  agg :avg_rating do
    { avg: { field: 'posts.rating' } }
  end
end
# File lib/chewy/index/mapping.rb, line 147
def agg(name, &block)
  self._agg_defs = _agg_defs.merge(name => block)
end
Also aliased as: aggregation
aggregation(name, &block)
Alias for: agg
dynamic_template(*args, **options)
Alias for: template
field(*args, **options, &block) click to toggle source

Defines mapping field for index

@example

class UsersIndex < Chewy::Index
  index_scope User
  # passing all the options to field definition:
  field :full_name, analyzer: 'special'
end

The `type` is optional and defaults to `string` if not defined:

@example

field :full_name

Also, multiple fields might be defined with one call and with the same options:

@example

field :first_name, :last_name, analyzer: 'special'

The only special option in the field definition is `:value`. If no `:value` specified then just corresponding method will be called for the indexed object. Also `:value` might be a proc or indexed object method name:

@example

class User < ActiveRecord::Base
  def user_full_name
    [first_name, last_name].join(' ')
  end
end

field :full_name, type: 'keyword', value: :user_full_name

The proc evaluates inside the indexed object context if its arity is 0 and in present contexts if there is an argument:

@example

field :full_name, type: 'keyword', value: -> { [first_name, last_name].join(' ') }

separator = ' '
field :full_name, type: 'keyword', value: ->(user) { [user.first_name, user.last_name].join(separator) }

If array was returned as value - it will be put in index as well.

@example

field :tags, type: 'keyword', value: -> { tags.map(&:name) }

Fields supports nesting in case of `object` field type. If `user.quiz` will return an array of objects, then result index content will be an array of hashes, if `user.quiz` is not a collection association then just values hash will be put in the index.

@example

field :quiz do
  field :question, :answer
  field :score, type: 'integer'
end

Nested fields are composed from nested objects:

@example

field :name, value: -> { name_translations } do
  field :ru, value: ->(name) { name['ru'] }
  field :en, value: ->(name) { name['en'] }
end

Of course it is possible to define object fields contents dynamically but make sure evaluation proc returns hash:

@example

field :name, type: 'object', value: -> { name_translations }

The special case is multi_field. If type options and block are both present field is treated as a multi-field. In that case field composition changes satisfy elasticsearch rules:

@example

field :full_name, type: 'text', analyzer: 'name', value: ->{ full_name.try(:strip) } do
  field :sorted, analyzer: 'sorted'
end
# File lib/chewy/index/mapping.rb, line 124
def field(*args, **options, &block)
  if args.size > 1
    args.map { |name| field(name, **options) }
  else
    expand_nested(Chewy::Fields::Base.new(args.first, **options), &block)
  end
end
mappings_hash() click to toggle source

Returns compiled mappings hash for current type

# File lib/chewy/index/mapping.rb, line 180
def mappings_hash
  root.mappings_hash
end
root(**options) { || ... } click to toggle source

Defines root object for mapping and is optional for index definition. Use it only if you need to pass options for root object mapping, such as `date_detection` or `dynamic_date_formats`

@example

class UsersIndex < Chewy::Index
  index_scope User
  # root object defined implicitly and optionless for current type
  field :full_name, type: 'keyword'
end

class CarsIndex < Chewy::Index
  index_scope Car
  # explicit root definition with additional options
  root dynamic_date_formats: ['yyyy-MM-dd'] do
    field :model_name, type: 'keyword'
  end
end
# File lib/chewy/index/mapping.rb, line 35
def root(**options)
  self.root_object ||= Chewy::Fields::Root.new(:root, **Chewy.default_root_options.merge(options))
  root_object.update_options!(**options)
  yield if block_given?
  root_object
end
supports_outdated_sync?() click to toggle source

Check whether the type has outdated_sync_field defined with a simple value.

@return [true, false]

# File lib/chewy/index/mapping.rb, line 187
def supports_outdated_sync?
  updated_at_field = root.child_hash[outdated_sync_field] if outdated_sync_field
  !!updated_at_field && updated_at_field.value.nil?
end
template(*args, **options) click to toggle source

Defines dynamic template in mapping root objects

@example

class CarsIndex < Chewy::Index
  index_scope Car
  template 'model.*', type: 'text', analyzer: 'special'
  field 'model', type: 'object' # here we can put { de: 'Der Mercedes', en: 'Mercedes' }
                                # and template will be applied to this field
end

Name for each template is generated with the following rule: `template_#!{dynamic_templates.size + 1}`.

@example Templates

template 'tit*', mapping_hash
template 'title.*', mapping_hash # dot in template causes "path_match" using
template /tit.+/, mapping_hash # using "match_pattern": "regexp"
template /title\..+/, mapping_hash # "\." - escaped dot causes "path_match" using
template /tit.+/, type: 'text', mapping_hash # "match_mapping_type" as an optional second argument
template template42: {match: 'hello*', mapping: {type: 'object'}} # or even pass a template as is
# File lib/chewy/index/mapping.rb, line 173
def template(*args, **options)
  root.dynamic_template(*args, **options)
end
Also aliased as: dynamic_template

Private Instance Methods

expand_nested(field) { || ... } click to toggle source
# File lib/chewy/index/mapping.rb, line 194
def expand_nested(field)
  @_current_field ||= root

  if @_current_field
    field.parent = @_current_field
    @_current_field.children.push(field)
  end

  return unless block_given?

  previous_field = @_current_field
  @_current_field = field
  yield
  @_current_field = previous_field
end