summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSean McGivern <sean@mcgivern.me.uk>2017-11-29 09:10:43 +0000
committerSean McGivern <sean@mcgivern.me.uk>2017-11-29 09:10:43 +0000
commita4f8dddc212fcd91f6a4a09e92b2de6117a21305 (patch)
treeeed31a76289f865cdb1d392c6bad3f2bf96ebbc4 /lib
parent3659327d71a033703451baba01873d5663755739 (diff)
parentda42dfb3cf4a2fb0cdcc1a3b41438516a0bed0e5 (diff)
downloadgitlab-ce-a4f8dddc212fcd91f6a4a09e92b2de6117a21305.tar.gz
Merge branch 'dm-search-pattern' into 'master'
Use fuzzy search with minimum length of 3 characters where appropriate Closes #40512 See merge request gitlab-org/gitlab-ce!15592
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/sql/pattern.rb25
1 files changed, 19 insertions, 6 deletions
diff --git a/lib/gitlab/sql/pattern.rb b/lib/gitlab/sql/pattern.rb
index 7c2d1d8f887..5f0c98cb5a4 100644
--- a/lib/gitlab/sql/pattern.rb
+++ b/lib/gitlab/sql/pattern.rb
@@ -4,9 +4,15 @@ module Gitlab
extend ActiveSupport::Concern
MIN_CHARS_FOR_PARTIAL_MATCHING = 3
- REGEX_QUOTED_WORD = /(?<=^| )"[^"]+"(?= |$)/
+ REGEX_QUOTED_WORD = /(?<=\A| )"[^"]+"(?= |\z)/
class_methods do
+ def fuzzy_search(query, columns)
+ matches = columns.map { |col| fuzzy_arel_match(col, query) }.compact.reduce(:or)
+
+ where(matches)
+ end
+
def to_pattern(query)
if partial_matching?(query)
"%#{sanitize_sql_like(query)}%"
@@ -19,12 +25,19 @@ module Gitlab
query.length >= MIN_CHARS_FOR_PARTIAL_MATCHING
end
- def to_fuzzy_arel(column, query)
- words = select_fuzzy_words(query)
+ def fuzzy_arel_match(column, query)
+ query = query.squish
+ return nil unless query.present?
- matches = words.map { |word| arel_table[column].matches(to_pattern(word)) }
+ words = select_fuzzy_words(query)
- matches.reduce { |result, match| result.and(match) }
+ if words.any?
+ words.map { |word| arel_table[column].matches(to_pattern(word)) }.reduce(:and)
+ 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
def select_fuzzy_words(query)
@@ -32,7 +45,7 @@ module Gitlab
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] }