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