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

Add better specs for query methods and query builder #104

Merged
merged 3 commits into from
Mar 26, 2024
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: 4 additions & 1 deletion lib/stretchy/attributes/transformers/keyword_transformer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ def protected?(arg)
# this is for text fields that have a keyword subfield
# `:text` and `:string` fields add a `:keyword` subfield to the attribute mapping automatically
def transform(item, *ignore)
return unless Stretchy.configuration.auto_target_keywords
return item unless Stretchy.configuration.auto_target_keywords
if item.is_a?(String)
return (!protected?(item) && keyword_available?(item)) ? "#{item}.#{keyword_field_for(item)}" : item
end
item.each_with_object({}) do |(key, value), new_item|
if ignore && ignore.include?(key)
new_item[key] = value
Expand Down
60 changes: 30 additions & 30 deletions lib/stretchy/relations/query_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def regexes
end

def fields
values[:field]
values[:fields]
end

def source
Expand Down Expand Up @@ -150,24 +150,21 @@ def build_query

structure.hybrid do
structure.queries do
hybrid[:neural].each do |n|
structure.child! do
params = n.dup
field_name, query_text = params.shift
structure.neural do
structure.set! field_name do
structure.query_text query_text
structure.extract! params, *params.keys
end
end
structure.child! do
params = hybrid[:neural].dup
field_name, query_text = params.shift
structure.neural do
structure.set! field_name do
structure.query_text query_text
structure.extract! params, *params.keys
end
end
end

hybrid[:query].each do |query|
structure.child! do
structure.extract! query, *query.keys
end
end
structure.child! do
hybrid_query = hybrid[:query].dup
structure.extract! hybrid_query, *hybrid_query.keys
end

end
end unless hybrid.nil?
Expand Down Expand Up @@ -222,7 +219,7 @@ def build_query

def build_regexp
regexes.each do |args|
target_field = args.first.keys.first
target_field = keyword_transformer.transform(args.first.keys.first.to_s)
value_field = args.first.values.first
structure.set! target_field, args.last.merge(value: value_field)
end
Expand Down Expand Up @@ -300,7 +297,7 @@ def build_search_options

def extra_search_options
unless self.count?
values[:size] = size.present? ? size : values[:default_size]
values[:size] = size.present? ? size : default_size
else
values[:size] = nil
end
Expand All @@ -310,7 +307,7 @@ def extra_search_options
def compact_where(q, opts = {bool:true})
return if q.nil?
if opts.delete(:bool)
as_must(q)
as_must([merge_and_append(q)])
else
as_query_string(q.flatten)
end
Expand Down Expand Up @@ -343,26 +340,29 @@ def as_query_string(q)

q.each do |arg|
arg.each_pair { |k,v| _and << "(#{k}:#{v})" } if arg.class == Hash
_and << "(#{arg})" if arg.class == String
if q.length == 1
_and << "#{arg}" if arg.class == String
else
_and << "(#{arg})" if arg.class == String
end
end
_and.join(" AND ")
end

def merge_and_append(queries)
builder = {}

queries.each do |q|
q.each do |k, v|
if builder.key?(k)
builder[k] = builder[k].class == Array ? builder[k] : [builder[k]]
builder[k] << v
result = {}
queries.each do |hash|
hash.each do |key, value|
if result[key].is_a?(Array)
result[key] << value
elsif result.key?(key)
result[key] = [result[key], value]
else
builder[k] = v
result[key] = value
end
end
end

builder
result
end

def extract_highlighter(highlighter)
Expand Down
2 changes: 1 addition & 1 deletion lib/stretchy/relations/query_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def registry
MULTI_VALUE_METHODS = [
:where,
:order,
:field,
:fields,
:highlight,
:source,
:must_not,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Stretchy
module Relations
module QueryMethods
module Field
module Fields
extend ActiveSupport::Concern

# Specify the fields to be returned by the Elasticsearch query.
Expand Down Expand Up @@ -49,16 +49,16 @@ module Field
# Model.fields('books.*')
# ```
#
def field(*args)
def fields(*args)
spawn.field!(*args)
end

# Alias for {#field}
# @see #field
alias :fields :field
alias :field :fields

def field!(*args) # :nodoc:
self.field_values += args
self.fields_values += args
self
end

Expand Down
2 changes: 1 addition & 1 deletion lib/stretchy/relations/query_methods/hybrid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def hybrid(opts)
end

def hybrid!(opts) # :nodoc:
self.hybrid_values += [opts]
self.hybrid_values = opts
self
end

Expand Down
16 changes: 3 additions & 13 deletions lib/stretchy/relations/query_methods/query_string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,12 @@ module QueryString
# ```
#
def query_string(opts = :chain, *rest)
if opts == :chain
WhereChain.new(spawn)
elsif opts.blank?
self
else
spawn.query_string!(opts, *rest)
end
spawn.query_string!(opts, *rest)
end

def query_string!(opts, *rest) # :nodoc:
if opts == :chain
WhereChain.new(self)
else
self.query_string_values += build_where(opts, rest)
self
end
self.query_string_values += build_where(opts, rest)
self
end

QueryMethods.register!(:query_string)
Expand Down
2 changes: 0 additions & 2 deletions lib/stretchy/relations/query_methods/regexp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ def regexp!(args) # :nodoc:
args = args.to_a
target_field, regex = args.shift
opts = args.to_h
opts.reverse_merge!(use_keyword: true)
target_field = "#{target_field}.keyword" if opts.delete(:use_keyword)
opts.merge!(case_insensitive: true) if regex.casefold?
self.regexp_values += [[Hash[target_field, regex.source], opts]]
self
Expand Down
7 changes: 5 additions & 2 deletions lib/stretchy/relations/query_methods/where.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ def where(opts = :chain, *rest)
opts.each do |key, value|
case value
when Range
opts.delete(key)
between(value, key)
range = opts.delete(key)
range_options = {gte: range.begin}
upper_bound = range.exclude_end? ? :lt : :lte
range_options[upper_bound] = range.end
filter_query(:range, key => range_options)
when Hash
opts.delete(key)
filter_query(:range, key => value) if value.keys.any? { |k| [:gte, :lte, :gt, :lt].include?(k) }
Expand Down
1 change: 1 addition & 0 deletions spec/models/test_model.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class TestModel < StretchyModel
attribute :name, :text
attribute :title, :keyword
attribute :age, :integer
attribute :tags, :array
attribute :data, :hash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class MyModel < Stretchy::Record

it 'does not transform' do
transformed_keywords = values[:where].map do |arg|
described_class.new(model.attribute_types).transform(arg)
expect(described_class.new(model.attribute_types).transform(arg)).to eq(arg)
end
end
end
Expand Down
9 changes: 0 additions & 9 deletions spec/stretchy/neural_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,6 @@
expect(described_class).to respond_to(:neural)
end

it 'adds values' do
values = described_class.neural(passage_embedding: { query_text: 'hello world', model_id: '1234'}).values[:neural]
expect(values.first).to eq({passage_embedding: { query_text: 'hello world', model_id: '1234'}})
end

it 'returns results' do
allow_any_instance_of(Elasticsearch::Persistence::Repository).to receive(:search).and_return(results)
expect(described_class.neural(passage_embedding: 'hello world', model_id: '1234', k:2).total).to eq(2)
Expand All @@ -152,10 +147,6 @@
expect(described_class).to respond_to(:hybrid)
end

it 'adds values' do
values = described_class.hybrid(neural: [{passage_embedding: 'hello world', model_id: '1234', k: 2}], query: [{term: {status: :active}}]).values[:hybrid]
expect(values).to eq([{neural: [{passage_embedding: 'hello world', model_id: '1234', k: 2}], query: [{term: {status: :active}}]}])
end
end


Expand Down
Loading
Loading