From d93a7edb950f4ba4b4d147894fb0baa7bf7eaffa Mon Sep 17 00:00:00 2001 From: Christian Sutter Date: Mon, 11 Dec 2023 12:17:09 +0000 Subject: [PATCH] Refactor expression types into classes --- .../all_string_filter_expression.rb | 11 ++++++++ .../any_string_filter_expression.rb | 9 ++++++ .../string_filter_expression.rb | 16 +++++++++++ .../discovery_engine/query/filters.rb | 28 ++----------------- 4 files changed, 39 insertions(+), 25 deletions(-) create mode 100644 app/services/discovery_engine/query/filter_expressions/all_string_filter_expression.rb create mode 100644 app/services/discovery_engine/query/filter_expressions/any_string_filter_expression.rb create mode 100644 app/services/discovery_engine/query/filter_expressions/string_filter_expression.rb 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