Skip to content

Commit

Permalink
Merge pull request #147 from alphagov/more-filters
Browse files Browse the repository at this point in the history
Refactor filters further
  • Loading branch information
csutter authored Dec 11, 2023
2 parents af11e8f + 7a6b33c commit 27e60b2
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
37 changes: 25 additions & 12 deletions app/services/discovery_engine/query/filters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ def initialize(query_params)
end

def filter_expression
surround_and_join([
expressions = [
reject_links_filter,
content_purpose_supergroup_filter,
], between: " AND ", surround: "(", surround_end: ")")
]

expressions
.compact
.map { surround(_1, delimiter: "(", delimiter_end: ")") }
.join(" AND ")
.presence
end

private
Expand All @@ -18,25 +24,32 @@ def filter_expression
def reject_links_filter
return nil if query_params[:reject_link].blank?

values = surround_and_join(query_params[:reject_link], between: ",", surround: '"')
values = Array(query_params[:reject_link])
.map { filter_string_value(_1) }
.join(",")

"NOT link: ANY(#{values})"
end

def content_purpose_supergroup_filter
return nil if query_params[:filter_content_purpose_supergroup].blank?

values = surround_and_join(
query_params[:filter_content_purpose_supergroup], between: ",", surround: '"'
)
values = Array(query_params[:filter_content_purpose_supergroup])
.map { filter_string_value(_1) }
.join(",")

"content_purpose_supergroup: ANY(#{values})"
end

def surround_and_join(string_or_strings, between:, surround:, surround_end: surround)
Array(string_or_strings)
.compact
.map { "#{surround}#{_1}#{surround_end}" }
.join(between)
.presence
# Input strings need to be wrapped in double quotes and have double quotes or backslashes
# escaped for Discovery Engine's filter syntax
def filter_string_value(str)
escaped_str = str.gsub(/(["\\])/, '\\\\\1')
surround(escaped_str, delimiter: '"')
end

def surround(str, delimiter:, delimiter_end: delimiter)
"#{delimiter}#{str}#{delimiter_end}"
end
end
end
6 changes: 6 additions & 0 deletions spec/services/discovery_engine/query/filters_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,11 @@

it { is_expected.to eq('(NOT link: ANY("/foo")) AND (content_purpose_supergroup: ANY("services"))') }
end

context "with filters containing escapable characters" do
let(:query_params) { { q: "garden centres", filter_content_purpose_supergroup: "foo\"\\bar" } }

it { is_expected.to eq('(content_purpose_supergroup: ANY("foo\\"\\\\bar"))') }
end
end
end

0 comments on commit 27e60b2

Please sign in to comment.