Class: Tire::Alias

Inherits:
Object
  • Object
show all
Defined in:
lib/tire/alias.rb

Overview

Represents an alias in ElasticSearch. An alias may point to one or multiple indices, for instance to separate physical indices into logical entities, where each user has a “virtual index” or for setting up “sliding window” scenarios.

See: www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html

Defined Under Namespace

Classes: IndexCollection

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}, &block) ⇒ Alias

Create an alias pointing to multiple indices:

Tire::Alias.create name: 'my_alias', indices: ['index_1', 'index_2']

Pass the routing and/or filtering configuration in the options Hash:

a = Tire::Alias.new name:    'index_anne',
                indices: ['index_2012_04', 'index_2012_03', 'index_2012_02'],
                routing: 1,
                filter:  { :terms => { :user => 'anne' } }
a.save

You may configure the alias in an imperative manner:

a = Tire::Alias.new
a.name('index_anne')
a.index('index_2012_04')
a.index('index_2012_03')
# ...
a.save

or more declaratively, with a block:

Tire::Alias.new name: 'my_alias' do
  index 'index_A'
  index 'index_B'
  filter :terms, username: 'mary'
end

To update an existing alias, find it by name, configure it and save it:

a = Tire::Alias.find('my_alias')
a.indices.delete 'index_A'
a.indices.add    'index_B'
a.indices.add    'index_C'
a.save

Or do it with a block:

Tire::Alias.find('articles_aliased') do |a|
  a.indices.remove 'articles_2'
  puts '---', "#{a.name} says: /me as JSON >", a.as_json, '---'
  a.save
end

To remove indices from alias, you may want to use the ‘delete_all` method:

require 'active_support/core_ext/numeric'
require 'active_support/core_ext/date/calculations'

a = Tire::Alias.find('articles_aliased')
a.indices.delete_if do |i|
  Time.parse( i.gsub(/articles_/, '') ) < 4.weeks.ago rescue false
end
a.save

To get all aliases, use the ‘Tire::Alias.all` method:

 Tire::Alias.all.each do |a|
  puts "#{a.name.rjust(30)} points to: #{a.indices}"
end

Raises:

  • (ArgumentError)


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/tire/alias.rb', line 74

def initialize(attributes={}, &block)
  raise ArgumentError, "Please pass a Hash-like object" unless attributes.respond_to?(:each_pair)

  @attributes = { :indices => IndexCollection.new([]) }

  attributes.each_pair do |key, value|
    if key.to_s =~ /index|indices/
      @attributes[:indices] = IndexCollection.new(value)
    else
      @attributes[key.to_sym] = value
    end
  end

  block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *arguments) ⇒ Object

Delegate to the ‘@attributes` Hash



130
131
132
# File 'lib/tire/alias.rb', line 130

def method_missing(method_name, *arguments)
  @attributes.has_key?(method_name.to_sym) ? @attributes[method_name.to_sym] : super
end

Class Method Details

.all(index = nil) ⇒ Object

Returns a collection of Tire::Alias objects for all aliases defined in the cluster, or for a specific index.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/tire/alias.rb', line 92

def self.all(index=nil)
  @response = Configuration.client.get [Configuration.url, index, '_aliases'].compact.join('/')

  aliases = MultiJson.decode(@response.body).inject({}) do |result, (index, value)|
    # 1] Skip indices without aliases
    next result if value['aliases'].empty?

    # 2] Build a reverse map of hashes (alias => indices, config)
    value['aliases'].each do |key, value| (result[key] ||= { 'indices' => [] }).update(value)['indices'].push(index) end
    result
  end

  # 3] Build a collection of Alias objects from hashes
  aliases.map do |key, value|
    self.new(value.update('name' => key))
  end

ensure
  # FIXME: Extract the `logged` method
  Alias.new.logged '_aliases', %Q|curl "#{Configuration.url}/_aliases"|
end

.create(attributes = {}, &block) ⇒ Object

Create new alias



124
125
126
# File 'lib/tire/alias.rb', line 124

def self.create(attributes={}, &block)
  new(attributes, &block).save
end

.find(name, &block) ⇒ Object

Returns an alias by name



116
117
118
119
120
# File 'lib/tire/alias.rb', line 116

def self.find(name, &block)
  a = all.select { |a| a.name == name }.first
  block.call(a) if block_given?
  return a
end

Instance Method Details

#as_json(options = nil) ⇒ Object

Return a Hash suitable for JSON serialization



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/tire/alias.rb', line 170

def as_json(options=nil)
  actions = []
  indices.add_indices.each do |index|
    operation = { :index => index, :alias => name }
    operation.update( { :routing => routing } ) if respond_to?(:routing) and routing
    operation.update( { :filter  => filter } )  if respond_to?(:filter)  and filter
    actions.push( { :add => operation } )
  end

  indices.remove_indices.each do |index|
    operation = { :index => index, :alias => name }
    actions.push( { :remove => operation } )
  end

  { :actions => actions }
end

#filter(type = nil, *options) ⇒ Object

Get or set the alias routing



155
156
157
# File 'lib/tire/alias.rb', line 155

def filter(type=nil, *options)
  type ? (@attributes[:filter] = Search::Filter.new(type, *options).to_hash and return self ) : @attributes[:filter]
end

#indices(*names) ⇒ Object Also known as: index

Get or set the alias indices



142
143
144
145
# File 'lib/tire/alias.rb', line 142

def indices(*names)
  names = Array(names).flatten
  names.compact.empty? ? @attributes[:indices] : (names.each { |n| @attributes[:indices].push(n) } and return self)
end

#inspectObject



193
194
195
# File 'lib/tire/alias.rb', line 193

def inspect
  %Q|<#{self.class} #{@attributes.inspect}>|
end

#logged(endpoint = '/', curl = '') ⇒ Object



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/tire/alias.rb', line 201

def logged(endpoint='/', curl='')
  # FIXME: Extract the `logged` method into module and mix it into classes
  if Configuration.logger
    error = $!

    Configuration.logger.log_request endpoint, @name, curl

    code = @response ? @response.code : error.class rescue 200

    if Configuration.logger.level.to_s == 'debug'
      body = if @response
        defined?(Yajl) ? Yajl::Encoder.encode(@response.body, :pretty => true) : MultiJson.encode(@response.body)
      else
        error.message rescue ''
      end
    else
      body = ''
    end

    Configuration.logger.log_response code, nil, body
  end
end

#name(value = nil) ⇒ Object

Get or set the alias name



136
137
138
# File 'lib/tire/alias.rb', line 136

def name(value=nil)
  value ? (@attributes[:name] = value and return self) : @attributes[:name]
end

#routing(value = nil) ⇒ Object

Get or set the alias routing



150
151
152
# File 'lib/tire/alias.rb', line 150

def routing(value=nil)
  value ? (@attributes[:routing] = value and return self) : @attributes[:routing]
end

#saveObject

Save the alias in ElasticSearch



161
162
163
164
165
166
# File 'lib/tire/alias.rb', line 161

def save
  @response = Configuration.client.post "#{Configuration.url}/_aliases", to_json

ensure
  logged '_aliases', %Q|curl -X POST "#{Configuration.url}/_aliases" -d '#{to_json}'|
end

#to_json(options = nil) ⇒ Object

Return alias serialized in JSON for ElasticSearch



189
190
191
# File 'lib/tire/alias.rb', line 189

def to_json(options=nil)
  as_json.to_json
end

#to_sObject



197
198
199
# File 'lib/tire/alias.rb', line 197

def to_s
  name
end