Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple indices in request #657

Merged
merged 1 commit into from
Oct 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why flatten? Array.wrap won't wrap arrays and you don't need flatten unless you expec someone to pass nested arrays there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect it actually

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