Skip to content

Commit

Permalink
v0.5.0
Browse files Browse the repository at this point in the history
- `terms_array_query` helper
- extracted `elastics_mapping` & `search_elastics` from AR to Model
- `Model.clear_elasics`
- compact format for mapping files
- `rake elastics:migrate full=true` => `rake elastics:migrate!`
  • Loading branch information
printercu committed Jan 14, 2015
1 parent 77a8168 commit c736bf9
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 24 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ creates index with settings for each file from `indices` folder.
- `rake elastics:migrate` (`.migrate`)
puts mappings from `mappings` folder.

- `rake elastics:migrate full=true` (`.migrate!`)
- `rake elastics:migrate!` (`.migrate!`)
performs full migration.

- `rake elastics:reindex` (`.reindex`)
Expand Down
21 changes: 9 additions & 12 deletions lib/elastics/active_record/helper_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,23 @@ def self.append_features(base)
end

module ClassMethods
# Performs `_search` request on type and instantiates result object.
# SearchResult is a default result class. It can be overriden with
# :result_class option.
def search_elastics(data = {}, options = {})
request = {
id: :_search,
body: data,
}
if routing = options[:routing]
request[:query] = {routing: routing}
end
SearchResult.new self, request_elastics(request), options
options[:result_class] ||= SearchResult
options[:model] = self
super
end

# Finds items by ids and returns array in the order in which ids were given.
# Every missing record is replaced with `nil` in the result.
def find_all_ordered(ids)
items_by_id = where(id: ids).index_by(&:id)
ids.map { |i| items_by_id[i] }
end

def elastics_mapping
request_elastics(method: :get, id: :_mapping)
end

# Indexes all records in current scope.
def index_all_elastics(*args)
find_in_batches(*args) do |batch|
index_batch_elastics(batch)
Expand Down
4 changes: 2 additions & 2 deletions lib/elastics/active_record/search_result.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module Elastics
module ActiveRecord
class SearchResult < Result::Search
def initialize(model, response, options = {})
@model = model
def initialize(response, options = {})
@model = options[:model]
super response, options
end

Expand Down
33 changes: 32 additions & 1 deletion lib/elastics/model/helper_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,37 @@ def elastics_params
}
end

# Proxies #request method to elastics client with specified index & type.
def request_elastics(params)
elastics.request(elastics_params.merge!(params))
end

# Proxies #bulk method to elastics client with specified index & type.
def bulk_elastics(params = {}, &block)
elastics.bulk(elastics_params.merge!(params), &block)
end

# Performs `_search` request on type and instantiates result object.
# Result::Search is a default result class. It can be overriden with
# :result_class option.
def search_elastics(data = {}, options = {})
request = {
id: :_search,
body: data,
}
if routing = options[:routing]
request[:query] = {routing: routing}
end
result_class = options[:result_class] || Result::Search
result_class.new request_elastics(request), options
end

# Performs `_refresh` request on index.
def refresh_elastics
request_elastics(method: :post, type: nil, id: :_refresh)
end

# Indexes given records using batch API.
def index_batch_elastics(batch)
bulk_elastics do |bulk|
batch.each do |record|
Expand All @@ -41,8 +60,20 @@ def index_batch_elastics(batch)
end
end

# Reindexes all records. It requires #find_in_batches method to be defined.
def reindex_elastics(options = {})
raise 'Not implemented'
find_in_batches(options) do |batch|
index_batch_elastics(batch)
end
end

# Deletes all records in type keeping its mapping using "Delete by query" API.
def clear_elastics
request_elastics method: :delete, id: :_query, body: {query: {match_all: {}}}
end

def elastics_mapping
request_elastics(id: :_mapping)
end
end

Expand Down
14 changes: 13 additions & 1 deletion lib/elastics/query_helper.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
module Elastics
module QueryHelper
# Combines multiple filters into `and` filter. Returns unmodified input
# unless it was an array.
def normalize_filters(filters)
return filters unless filters.is_a?(Array)
return filters[0] if 2 > filters.size
{and: {filters: filters}}
end

# Wraps given query into `filtered` query if filter is present.
# Also replaces empty query with `match_all`.
def normalize_query(query, filters)
filter = normalize_filters filters
query ||= {match_all: {}}
Expand All @@ -16,12 +20,20 @@ def normalize_query(query, filters)
}}
end

# Returns `term`(for scalar value) or `terms` (for array) query node
# for specified field.
def terms_query(field, val, options = {})
if val.is_a?(Array)
{terms: {field => val}.merge(options)}
else
result = {term: {field => val}}
{term: {field => val}}
end
end

# Returns `nil` if falsy value or empty array is given. Other way
# it returns term(s) query for it.
def terms_array_query(field, val, options = {})
terms_query(field, val, options) if val && (!val.is_a?(Array) || val.any?)
end
end
end
26 changes: 25 additions & 1 deletion lib/elastics/tasks/mappings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,34 @@ def mappings
flatten.sort.
each_with_object({}) do |file, hash|
name = File.basename file, '.yml'
hash[name] = YAML.load_file(file)
hash[name] = fix_mapping(name, YAML.load_file(file))
end
end

# Adds missing type name in the top-level and updates properties definition.
# It allows to write
#
# properties:
# name: string
# project_id: integer
#
# instead of
#
# task:
# properties:
# name:
# type: string
# project_id:
# type: integer
def fix_mapping(name, mapping)
mapping = {name => mapping} unless mapping.keys == [name]
properties = mapping[name]['properties']
properties && properties.each do |field, val|
properties[field] = {type: val} if val.is_a?(String)
end
mapping
end

def types
@types ||= mappings.keys
end
Expand Down
2 changes: 1 addition & 1 deletion lib/elastics/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Elastics
VERSION = '0.4.0'
VERSION = '0.5.0'

def self.gem_version
Gem::Version.new VERSION
Expand Down
10 changes: 5 additions & 5 deletions lib/tasks/elastics.rake
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ namespace 'elastics' do

desc 'Creates indices and applies mappings. Full migration when param is present'
task migrate: :load_config do
if ENV['full']
Elastics::Tasks.migrate! @elastics_options
else
Elastics::Tasks.migrate @elastics_options
end
Elastics::Tasks.migrate @elastics_options
end

task migrate!: :load_config do
Elastics::Tasks.migrate! @elastics_options
end

desc 'Reindex'
Expand Down

0 comments on commit c736bf9

Please sign in to comment.