[Search 2.0] Match both word boundaries when filtering tags (#13554)

This commit is contained in:
rhymes 2021-04-28 11:24:45 +02:00 committed by GitHub
parent 1a48b3151a
commit 8762815709
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 14 additions and 5 deletions

View file

@ -69,10 +69,11 @@ module Homepage
# would put all the previous filters in `OR` mode with tags, but what we need
# is to only consider tags as a `OR` sub-condition
if tags.present?
# `~` is the regexp operator and the `\M` modifier signifies the "end of word"
# `~` is the regexp operator, the `\m` modifier signifies the "beginning of word",
# and the `\M` modifier signifies the "end of word".
# see https://www.postgresql.org/docs/11/functions-matching.html#FUNCTIONS-POSIX-REGEXP
# for additional info
conditions = tags.map { |tag| relation.sanitize_sql_array(["cached_tag_list ~ ?", "#{tag}\\M"]) }
conditions = tags.map { |tag| relation.sanitize_sql_array(["cached_tag_list ~ ?", "\\m#{tag}\\M"]) }
@relation = @relation.where(conditions.join(" OR "))
end

View file

@ -94,7 +94,7 @@ module Search
# The preferred solution, as we don't need the `Tag` model itself, is to use
# `articles.cached_tag_list` and the `~` regexp operator with it
tags.each do |tag|
relation = relation.where("articles.cached_tag_list ~ ?", "#{tag}\\M")
relation = relation.where("articles.cached_tag_list ~ ?", "\\m#{tag}\\M")
end
# here we issue a COUNT(*) after all the conditions are applied,

View file

@ -127,11 +127,13 @@ RSpec.describe Homepage::ArticlesQuery, type: :query do
expect(described_class.call(tags: %i[beginners ruby]).ids).to match_array([article1.id, article2.id])
end
it "does not return results for partial matches" do
it "does not return results for partial matches", :aggregate_failures do
article1.tag_list.add(:javascript)
article1.save
expect(described_class.call(tags: %i[java]).ids).to be_empty
expect(described_class.call(tags: %i[asc]).ids).to be_empty
expect(described_class.call(tags: %i[script]).ids).to be_empty
end
end

View file

@ -167,7 +167,7 @@ RSpec.describe Search::Postgres::ReadingList, type: :service do
expect(extract_from_results(result, :path)).not_to include(article_2.path)
end
it "does not match on partial tags" do
it "does not match on partial tags", :aggregate_failures do
article_1.tag_list.add(:javascript)
article_1.save!
@ -175,6 +175,12 @@ RSpec.describe Search::Postgres::ReadingList, type: :service do
result = described_class.search_documents(user, tags: [:java])
expect(extract_from_results(result, :path)).to be_empty
result = described_class.search_documents(user, tags: [:asc])
expect(extract_from_results(result, :path)).to be_empty
result = described_class.search_documents(user, tags: [:script])
expect(extract_from_results(result, :path)).to be_empty
end
end