Skip to content

Commit

Permalink
Merge pull request #657 from toptal/multiple-indices-request
Browse files Browse the repository at this point in the history
Support multiple indices in request
  • Loading branch information
pyromaniac authored Oct 25, 2018
2 parents ac461c4 + 489bf5c commit cb1bb3e
Show file tree
Hide file tree
Showing 10 changed files with 425 additions and 158 deletions.
5 changes: 5 additions & 0 deletions lib/chewy/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ def initialize(*indexes_or_types_and_options)
@criteria = Criteria.new
end

# A compatibility layer with the new request DSL.
def render
_request
end

# Comparation with other query or collection
# If other is collection - search request is executed and
# result is used for comparation
Expand Down
6 changes: 1 addition & 5 deletions lib/chewy/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,7 @@ def all
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
# @return [Hash] the request result
def search_string(query, options = {})
options = options.merge(
index: all._indexes.map(&:index_name),
type: all._types.map(&:type_name),
q: query
)
options = options.merge(all.render.slice(:index, :type).merge(q: query))
Chewy.client.search(options)
end

Expand Down
16 changes: 10 additions & 6 deletions lib/chewy/search/parameters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ module Search
# @see Chewy::Search::Request#parameters
# @see Chewy::Search::Parameters::Storage
class Parameters
QUERY_STRING_PARAMS = %i[search_type request_cache allow_partial_search_results].freeze
QUERY_STRING_STORAGES = %i[indices search_type request_cache allow_partial_search_results].freeze

# Default storage classes warehouse. It is probably possible to
# add your own classes here if necessary, but I'm not sure it will work.
#
Expand Down Expand Up @@ -102,7 +103,7 @@ def merge!(other)
#
# @return [Hash] request body
def render
{}.merge(render_body).merge(render_query_string_params)
render_query_string_params.merge(render_body)
end

protected
Expand All @@ -124,19 +125,22 @@ def assert_storages(names)
end

def render_query_string_params
stores = @storages.select { |storage_name, _| QUERY_STRING_PARAMS.include?(storage_name) }
stores.values.inject({}) do |result, storage|
query_string_storages = @storages.select do |storage_name, _|
QUERY_STRING_STORAGES.include?(storage_name)
end

query_string_storages.values.inject({}) do |result, storage|
result.merge!(storage.render || {})
end
end

def render_body
exceptions = %i[filter query none] + QUERY_STRING_PARAMS
exceptions = %i[filter query none] + QUERY_STRING_STORAGES
body = @storages.except(*exceptions).values.inject({}) do |result, storage|
result.merge!(storage.render || {})
end
body.merge!(render_query || {})
body.present? ? {body: body} : {}
{body: body}
end

def render_query
Expand Down
123 changes: 123 additions & 0 deletions lib/chewy/search/parameters/indices.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
require 'chewy/search/parameters/storage'

module Chewy
module Search
class Parameters
# Stores indices and/or types to query.
# Renders it to lists of string accepted by ElasticSearch
# API.
#
# The semantics behind it can be described in the
# following statements:
# 1. If index is added to the storage, no matter, a class
# or a string/symbol, it gets appended to the list.
# 2. If type is added to the storage, it filters out types
# assigned via indices.
# 3. But when a type class with non-existing index is added,
# this index got also added to the list if indices.
# 4. In cases when of an index identifier added, type
# indetifiers also got appended instead of filtering.
class Indices < Storage
# Two index storages are equal if they produce the
# same output on render.
#
# @see Chewy::Search::Parameters::Storage#==
# @param other [Chewy::Search::Parameters::Storage] any storage instance
# @return [true, false] the result of comparision
def ==(other)
super || other.class == self.class && other.render == render
end

# Just adds types to types and indices to indices.
#
# @see Chewy::Search::Parameters::Storage#update!
# @param other_value [{Symbol => Array<Chewy::Index, Chewy::Type, String, Symbol>}] any acceptable storage value
# @return [{Symbol => Array<Chewy::Index, Chewy::Type, String, Symbol>}] updated value
def update!(other_value)
new_value = normalize(other_value)

@value = {
indices: value[:indices] | new_value[:indices],
types: value[:types] | new_value[:types]
}
end

# Returns desired index and type names.
#
# @see Chewy::Search::Parameters::Storage#render
# @return [{Symbol => Array<String>}] rendered value with the parameter name
def render
{
index: index_names.uniq.sort,
type: type_names.uniq.sort
}.reject { |_, v| v.blank? }
end

# Returns index classes used for the request.
# No strings/symbos included.
#
# @return [Array<Chewy::Index>] a list of index classes
def indices
index_classes | type_classes.map(&:index)
end

# Returns type classes used for the request.
# No strings/symbos included.
#
# @return [Array<Chewy::Type>] a list of types classes
def types
type_classes | (index_classes - type_classes.map(&:index)).flat_map(&:types)
end

private

def initialize_clone(origin)
@value = origin.value.dup
end

def normalize(value)
value ||= {}

{
indices: Array.wrap(value[:indices]).flatten.compact,
types: Array.wrap(value[:types]).flatten.compact
}
end

def index_classes
value[:indices].select do |klass|
klass.is_a?(Class) && klass < Chewy::Index
end
end

def index_identifiers
value[:indices] - index_classes
end

def index_names
indices.map(&:index_name) | index_identifiers.map(&:to_s)
end

def type_classes
value[:types].select do |klass|
klass.is_a?(Class) && klass < Chewy::Type
end
end

def type_identifiers
value[:types] - type_classes
end

def type_names
type_names = types.map(&:type_name)

if index_identifiers.blank? && type_identifiers.present?
(type_names & type_identifiers.map(&:to_s)).presence || type_names
else
type_names | type_identifiers.map(&:to_s)
end
end
end
end
end
end
Loading

0 comments on commit cb1bb3e

Please sign in to comment.