Modify fuzzy_arel_match to search for equality when a term shorter than 3 characters is provided
This commit is contained in:
parent
b2c5363da1
commit
d4eea27531
2 changed files with 30 additions and 7 deletions
|
@ -4,7 +4,7 @@ module Gitlab
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
MIN_CHARS_FOR_PARTIAL_MATCHING = 3
|
MIN_CHARS_FOR_PARTIAL_MATCHING = 3
|
||||||
REGEX_QUOTED_WORD = /(?<=^| )"[^"]+"(?= |$)/
|
REGEX_QUOTED_WORD = /(?<=\A| )"[^"]+"(?= |\z)/
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
def to_pattern(query)
|
def to_pattern(query)
|
||||||
|
@ -20,11 +20,18 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def fuzzy_arel_match(column, query)
|
def fuzzy_arel_match(column, query)
|
||||||
|
query = query.squish
|
||||||
|
return nil unless query.present?
|
||||||
|
|
||||||
words = select_fuzzy_words(query)
|
words = select_fuzzy_words(query)
|
||||||
|
|
||||||
matches = words.map { |word| arel_table[column].matches(to_pattern(word)) }
|
if words.any?
|
||||||
|
words.map { |word| arel_table[column].matches(to_pattern(word)) }.reduce(:and)
|
||||||
matches.reduce { |result, match| result.and(match) }
|
else
|
||||||
|
# No words of at least 3 chars, but we can search for an exact
|
||||||
|
# case insensitive match with the query as a whole
|
||||||
|
arel_table[column].matches(sanitize_sql_like(query))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def select_fuzzy_words(query)
|
def select_fuzzy_words(query)
|
||||||
|
@ -32,7 +39,7 @@ module Gitlab
|
||||||
|
|
||||||
query = quoted_words.reduce(query) { |q, quoted_word| q.sub(quoted_word, '') }
|
query = quoted_words.reduce(query) { |q, quoted_word| q.sub(quoted_word, '') }
|
||||||
|
|
||||||
words = query.split(/\s+/)
|
words = query.split
|
||||||
|
|
||||||
quoted_words.map! { |quoted_word| quoted_word[1..-2] }
|
quoted_words.map! { |quoted_word| quoted_word[1..-2] }
|
||||||
|
|
||||||
|
|
|
@ -151,8 +151,8 @@ describe Gitlab::SQL::Pattern do
|
||||||
context 'with a word shorter than 3 chars' do
|
context 'with a word shorter than 3 chars' do
|
||||||
let(:query) { 'fo' }
|
let(:query) { 'fo' }
|
||||||
|
|
||||||
it 'returns nil' do
|
it 'returns a single equality condition' do
|
||||||
expect(fuzzy_arel_match).to be_nil
|
expect(fuzzy_arel_match.to_sql).to match(/title.*I?LIKE 'fo'/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -164,6 +164,22 @@ describe Gitlab::SQL::Pattern do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with two words both shorter than 3 chars' do
|
||||||
|
let(:query) { 'fo ba' }
|
||||||
|
|
||||||
|
it 'returns a single ILIKE condition' do
|
||||||
|
expect(fuzzy_arel_match.to_sql).to match(/title.*I?LIKE 'fo ba'/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with two words, one shorter 3 chars' do
|
||||||
|
let(:query) { 'foo ba' }
|
||||||
|
|
||||||
|
it 'returns a single ILIKE condition using the longer word' do
|
||||||
|
expect(fuzzy_arel_match.to_sql).to match(/title.+I?LIKE '\%foo\%'/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'with a multi-word surrounded by double quote and two words' do
|
context 'with a multi-word surrounded by double quote and two words' do
|
||||||
let(:query) { 'foo "really bar" baz' }
|
let(:query) { 'foo "really bar" baz' }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue