diff options
author | Sean McGivern <sean@mcgivern.me.uk> | 2017-11-29 09:10:43 +0000 |
---|---|---|
committer | Sean McGivern <sean@mcgivern.me.uk> | 2017-11-29 09:10:43 +0000 |
commit | a4f8dddc212fcd91f6a4a09e92b2de6117a21305 (patch) | |
tree | eed31a76289f865cdb1d392c6bad3f2bf96ebbc4 /lib | |
parent | 3659327d71a033703451baba01873d5663755739 (diff) | |
parent | da42dfb3cf4a2fb0cdcc1a3b41438516a0bed0e5 (diff) | |
download | gitlab-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.rb | 25 |
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] } |