diff --git a/app/services/discovery_engine/query/filter_expressions/all_string_filter_expression.rb b/app/services/discovery_engine/query/filter_expressions/all_string_filter_expression.rb new file mode 100644 index 0000000..f84ce52 --- /dev/null +++ b/app/services/discovery_engine/query/filter_expressions/all_string_filter_expression.rb @@ -0,0 +1,11 @@ +module DiscoveryEngine::Query::FilterExpressions + class AllStringFilterExpression < StringFilterExpression + def expression + return if values.empty? + + # There is no `ALL` equivalent for `ANY` in Discovery Engine, so we need to join up multiple + # `ANY` expressions to achieve the same effect. + values.map { "#{field}: ANY(#{_1})" }.join(" AND ") + end + end +end diff --git a/app/services/discovery_engine/query/filter_expressions/any_string_filter_expression.rb b/app/services/discovery_engine/query/filter_expressions/any_string_filter_expression.rb new file mode 100644 index 0000000..25306ac --- /dev/null +++ b/app/services/discovery_engine/query/filter_expressions/any_string_filter_expression.rb @@ -0,0 +1,9 @@ +module DiscoveryEngine::Query::FilterExpressions + class AnyStringFilterExpression < StringFilterExpression + def expression + return if values.empty? + + "#{field}: ANY(#{values.join(',')})" + end + end +end diff --git a/app/services/discovery_engine/query/filter_expressions/string_filter_expression.rb b/app/services/discovery_engine/query/filter_expressions/string_filter_expression.rb new file mode 100644 index 0000000..e12cb71 --- /dev/null +++ b/app/services/discovery_engine/query/filter_expressions/string_filter_expression.rb @@ -0,0 +1,16 @@ +module DiscoveryEngine::Query::FilterExpressions + class StringFilterExpression + def initialize(field, value_or_values) + @field = field + @values = Array(value_or_values).compact_blank.map { StringValue.new(_1) } + end + + def negated_expression + "NOT #{expression}" + end + + private + + attr_reader :field, :values + end +end diff --git a/app/services/discovery_engine/query/filters.rb b/app/services/discovery_engine/query/filters.rb index e6b0bcf..a0390f8 100644 --- a/app/services/discovery_engine/query/filters.rb +++ b/app/services/discovery_engine/query/filters.rb @@ -8,9 +8,9 @@ def initialize(query_params) def filter_expression expressions = [ - *query_params_of_type(:reject).map { reject_filter(_1, _2) }, - *query_params_of_type(:filter).map { any_filter(_1, _2) }, - *query_params_of_type(:filter_all).map { all_filter(_1, _2) }, + *query_params_of_type(:reject).map { FilterExpressions::AnyStringFilterExpression.new(_1, _2).negated_expression }, + *query_params_of_type(:filter).map { FilterExpressions::AnyStringFilterExpression.new(_1, _2).expression }, + *query_params_of_type(:filter_all).map { FilterExpressions::AllStringFilterExpression.new(_1, _2).expression }, ].compact expressions @@ -29,27 +29,5 @@ def query_params_of_type(type) .to_h .compact_blank end - - def reject_filter(field, value_or_values) - string_filter_expression(field, value_or_values, negate: true) - end - - def all_filter(field, value_or_values) - Array(value_or_values) - .map { string_filter_expression(field, _1) } - .join(" AND ") - .presence - end - - def any_filter(field, value_or_values) - string_filter_expression(field, value_or_values) - end - - def string_filter_expression(field, value_or_values, negate: false) - values = Array(value_or_values).map { FilterExpressions::StringValue.new(_1) } - return if values.blank? - - "#{negate ? 'NOT ' : ''}#{field}: ANY(#{values.join(',')})" - end end end