Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
da42dfb3
Commit
da42dfb3
authored
Nov 24, 2017
by
Douwe Maan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use fuzzy search with minimum length of 3 characters where appropriate
parent
d4eea275
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
39 additions
and
54 deletions
+39
-54
app/models/ci/runner.rb
app/models/ci/runner.rb
+1
-4
app/models/concerns/issuable.rb
app/models/concerns/issuable.rb
+2
-7
app/models/email.rb
app/models/email.rb
+1
-0
app/models/milestone.rb
app/models/milestone.rb
+1
-4
app/models/namespace.rb
app/models/namespace.rb
+1
-4
app/models/note.rb
app/models/note.rb
+1
-1
app/models/project.rb
app/models/project.rb
+2
-8
app/models/snippet.rb
app/models/snippet.rb
+2
-5
app/models/user.rb
app/models/user.rb
+9
-15
changelogs/unreleased/dm-search-pattern.yml
changelogs/unreleased/dm-search-pattern.yml
+5
-0
lib/gitlab/sql/pattern.rb
lib/gitlab/sql/pattern.rb
+6
-0
spec/models/ci/runner_spec.rb
spec/models/ci/runner_spec.rb
+1
-1
spec/models/concerns/issuable_spec.rb
spec/models/concerns/issuable_spec.rb
+6
-4
spec/models/snippet_spec.rb
spec/models/snippet_spec.rb
+1
-1
No files found.
app/models/ci/runner.rb
View file @
da42dfb3
...
@@ -60,10 +60,7 @@ module Ci
...
@@ -60,10 +60,7 @@ module Ci
#
#
# Returns an ActiveRecord::Relation.
# Returns an ActiveRecord::Relation.
def
self
.
search
(
query
)
def
self
.
search
(
query
)
t
=
arel_table
fuzzy_search
(
query
,
[
:token
,
:description
])
pattern
=
to_pattern
(
query
)
where
(
t
[
:token
].
matches
(
pattern
).
or
(
t
[
:description
].
matches
(
pattern
)))
end
end
def
self
.
contact_time_deadline
def
self
.
contact_time_deadline
...
...
app/models/concerns/issuable.rb
View file @
da42dfb3
...
@@ -122,9 +122,7 @@ module Issuable
...
@@ -122,9 +122,7 @@ module Issuable
#
#
# Returns an ActiveRecord::Relation.
# Returns an ActiveRecord::Relation.
def
search
(
query
)
def
search
(
query
)
title
=
fuzzy_arel_match
(
:title
,
query
)
fuzzy_search
(
query
,
[
:title
])
where
(
title
)
end
end
# Searches for records with a matching title or description.
# Searches for records with a matching title or description.
...
@@ -135,10 +133,7 @@ module Issuable
...
@@ -135,10 +133,7 @@ module Issuable
#
#
# Returns an ActiveRecord::Relation.
# Returns an ActiveRecord::Relation.
def
full_search
(
query
)
def
full_search
(
query
)
title
=
fuzzy_arel_match
(
:title
,
query
)
fuzzy_search
(
query
,
[
:title
,
:description
])
description
=
fuzzy_arel_match
(
:description
,
query
)
where
(
title
&
.
or
(
description
))
end
end
def
sort
(
method
,
excluded_labels:
[])
def
sort
(
method
,
excluded_labels:
[])
...
...
app/models/email.rb
View file @
da42dfb3
class
Email
<
ActiveRecord
::
Base
class
Email
<
ActiveRecord
::
Base
include
Sortable
include
Sortable
include
Gitlab
::
SQL
::
Pattern
belongs_to
:user
belongs_to
:user
...
...
app/models/milestone.rb
View file @
da42dfb3
...
@@ -74,10 +74,7 @@ class Milestone < ActiveRecord::Base
...
@@ -74,10 +74,7 @@ class Milestone < ActiveRecord::Base
#
#
# Returns an ActiveRecord::Relation.
# Returns an ActiveRecord::Relation.
def
search
(
query
)
def
search
(
query
)
t
=
arel_table
fuzzy_search
(
query
,
[
:title
,
:description
])
pattern
=
to_pattern
(
query
)
where
(
t
[
:title
].
matches
(
pattern
).
or
(
t
[
:description
].
matches
(
pattern
)))
end
end
def
filter_by_state
(
milestones
,
state
)
def
filter_by_state
(
milestones
,
state
)
...
...
app/models/namespace.rb
View file @
da42dfb3
...
@@ -87,10 +87,7 @@ class Namespace < ActiveRecord::Base
...
@@ -87,10 +87,7 @@ class Namespace < ActiveRecord::Base
#
#
# Returns an ActiveRecord::Relation
# Returns an ActiveRecord::Relation
def
search
(
query
)
def
search
(
query
)
t
=
arel_table
fuzzy_search
(
query
,
[
:name
,
:path
])
pattern
=
to_pattern
(
query
)
where
(
t
[
:name
].
matches
(
pattern
).
or
(
t
[
:path
].
matches
(
pattern
)))
end
end
def
clean_path
(
path
)
def
clean_path
(
path
)
...
...
app/models/note.rb
View file @
da42dfb3
...
@@ -170,7 +170,7 @@ class Note < ActiveRecord::Base
...
@@ -170,7 +170,7 @@ class Note < ActiveRecord::Base
end
end
def
search
(
query
)
def
search
(
query
)
where
(
arel_table
[
:note
].
matches
(
to_pattern
(
query
))
)
fuzzy_search
(
query
,
[
:note
]
)
end
end
end
end
...
...
app/models/project.rb
View file @
da42dfb3
...
@@ -425,17 +425,11 @@ class Project < ActiveRecord::Base
...
@@ -425,17 +425,11 @@ class Project < ActiveRecord::Base
#
#
# query - The search query as a String.
# query - The search query as a String.
def
search
(
query
)
def
search
(
query
)
pattern
=
to_pattern
(
query
)
fuzzy_search
(
query
,
[
:path
,
:name
,
:description
])
where
(
arel_table
[
:path
].
matches
(
pattern
)
.
or
(
arel_table
[
:name
].
matches
(
pattern
))
.
or
(
arel_table
[
:description
].
matches
(
pattern
))
)
end
end
def
search_by_title
(
query
)
def
search_by_title
(
query
)
non_archived
.
where
(
arel_table
[
:name
].
matches
(
to_pattern
(
query
))
)
non_archived
.
fuzzy_search
(
query
,
[
:name
]
)
end
end
def
visibility_levels
def
visibility_levels
...
...
app/models/snippet.rb
View file @
da42dfb3
...
@@ -136,10 +136,7 @@ class Snippet < ActiveRecord::Base
...
@@ -136,10 +136,7 @@ class Snippet < ActiveRecord::Base
#
#
# Returns an ActiveRecord::Relation.
# Returns an ActiveRecord::Relation.
def
search
(
query
)
def
search
(
query
)
t
=
arel_table
fuzzy_search
(
query
,
[
:title
,
:
file_name
])
pattern
=
to_pattern
(
query
)
where
(
t
[
:title
].
matches
(
pattern
).
or
(
t
[:
file_name
].
matches
(
pattern
)))
end
end
# Searches for snippets with matching content.
# Searches for snippets with matching content.
...
@@ -150,7 +147,7 @@ class Snippet < ActiveRecord::Base
...
@@ -150,7 +147,7 @@ class Snippet < ActiveRecord::Base
#
#
# Returns an ActiveRecord::Relation.
# Returns an ActiveRecord::Relation.
def
search_code
(
query
)
def
search_code
(
query
)
where
(
arel_table
[
:content
].
matches
(
to_pattern
(
query
))
)
fuzzy_search
(
query
,
[
:content
]
)
end
end
end
end
end
end
app/models/user.rb
View file @
da42dfb3
...
@@ -313,9 +313,6 @@ class User < ActiveRecord::Base
...
@@ -313,9 +313,6 @@ class User < ActiveRecord::Base
#
#
# Returns an ActiveRecord::Relation.
# Returns an ActiveRecord::Relation.
def
search
(
query
)
def
search
(
query
)
table
=
arel_table
pattern
=
User
.
to_pattern
(
query
)
order
=
<<~
SQL
order
=
<<~
SQL
CASE
CASE
WHEN users.name = %{query} THEN 0
WHEN users.name = %{query} THEN 0
...
@@ -325,11 +322,8 @@ class User < ActiveRecord::Base
...
@@ -325,11 +322,8 @@ class User < ActiveRecord::Base
END
END
SQL
SQL
where
(
fuzzy_search
(
query
,
[
:name
,
:email
,
:username
])
table
[
:name
].
matches
(
pattern
)
.
reorder
(
order
%
{
query:
ActiveRecord
::
Base
.
connection
.
quote
(
query
)
},
:name
)
.
or
(
table
[
:email
].
matches
(
pattern
))
.
or
(
table
[
:username
].
matches
(
pattern
))
).
reorder
(
order
%
{
query:
ActiveRecord
::
Base
.
connection
.
quote
(
query
)
},
:name
)
end
end
# searches user by given pattern
# searches user by given pattern
...
@@ -337,16 +331,16 @@ class User < ActiveRecord::Base
...
@@ -337,16 +331,16 @@ class User < ActiveRecord::Base
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
def
search_with_secondary_emails
(
query
)
def
search_with_secondary_emails
(
query
)
table
=
arel_table
email_table
=
Email
.
arel_table
email_table
=
Email
.
arel_table
pattern
=
to_pattern
(
query
)
matched_by_emails_user_ids
=
email_table
matched_by_emails_user_ids
=
email_table
.
project
(
email_table
[
:user_id
]).
where
(
email_table
[
:email
].
matches
(
pattern
))
.
project
(
email_table
[
:user_id
])
.
where
(
Email
.
fuzzy_arel_match
(
:email
,
query
))
where
(
where
(
table
[
:name
].
matches
(
pattern
)
fuzzy_arel_match
(
:name
,
query
)
.
or
(
table
[
:email
].
matches
(
pattern
))
.
or
(
fuzzy_arel_match
(
:email
,
query
))
.
or
(
table
[
:username
].
matches
(
pattern
))
.
or
(
fuzzy_arel_match
(
:username
,
query
))
.
or
(
table
[
:id
].
in
(
matched_by_emails_user_ids
))
.
or
(
arel_
table
[
:id
].
in
(
matched_by_emails_user_ids
))
)
)
end
end
...
...
changelogs/unreleased/dm-search-pattern.yml
0 → 100644
View file @
da42dfb3
---
title
:
Use fuzzy search with minimum length of 3 characters where appropriate
merge_request
:
author
:
type
:
performance
lib/gitlab/sql/pattern.rb
View file @
da42dfb3
...
@@ -7,6 +7,12 @@ module Gitlab
...
@@ -7,6 +7,12 @@ module Gitlab
REGEX_QUOTED_WORD
=
/(?<=\A| )"[^"]+"(?= |\z)/
REGEX_QUOTED_WORD
=
/(?<=\A| )"[^"]+"(?= |\z)/
class_methods
do
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
)
def
to_pattern
(
query
)
if
partial_matching?
(
query
)
if
partial_matching?
(
query
)
"%
#{
sanitize_sql_like
(
query
)
}
%"
"%
#{
sanitize_sql_like
(
query
)
}
%"
...
...
spec/models/ci/runner_spec.rb
View file @
da42dfb3
...
@@ -473,7 +473,7 @@ describe Ci::Runner do
...
@@ -473,7 +473,7 @@ describe Ci::Runner do
end
end
describe
'.search'
do
describe
'.search'
do
let
(
:runner
)
{
create
(
:ci_runner
,
token:
'123abc'
)
}
let
(
:runner
)
{
create
(
:ci_runner
,
token:
'123abc'
,
description:
'test runner'
)
}
it
'returns runners with a matching token'
do
it
'returns runners with a matching token'
do
expect
(
described_class
.
search
(
runner
.
token
)).
to
eq
([
runner
])
expect
(
described_class
.
search
(
runner
.
token
)).
to
eq
([
runner
])
...
...
spec/models/concerns/issuable_spec.rb
View file @
da42dfb3
...
@@ -67,6 +67,7 @@ describe Issuable do
...
@@ -67,6 +67,7 @@ describe Issuable do
describe
".search"
do
describe
".search"
do
let!
(
:searchable_issue
)
{
create
(
:issue
,
title:
"Searchable awesome issue"
)
}
let!
(
:searchable_issue
)
{
create
(
:issue
,
title:
"Searchable awesome issue"
)
}
let!
(
:searchable_issue2
)
{
create
(
:issue
,
title:
'Aw'
)
}
it
'returns issues with a matching title'
do
it
'returns issues with a matching title'
do
expect
(
issuable_class
.
search
(
searchable_issue
.
title
))
expect
(
issuable_class
.
search
(
searchable_issue
.
title
))
...
@@ -86,8 +87,8 @@ describe Issuable do
...
@@ -86,8 +87,8 @@ describe Issuable do
expect
(
issuable_class
.
search
(
'searchable issue'
)).
to
eq
([
searchable_issue
])
expect
(
issuable_class
.
search
(
'searchable issue'
)).
to
eq
([
searchable_issue
])
end
end
it
'returns
all issues with
a query shorter than 3 chars'
do
it
'returns
issues with a matching title for
a query shorter than 3 chars'
do
expect
(
issuable_class
.
search
(
'zz'
)).
to
eq
(
issuable_class
.
all
)
expect
(
issuable_class
.
search
(
searchable_issue2
.
title
.
downcase
)).
to
eq
([
searchable_issue2
]
)
end
end
end
end
...
@@ -95,6 +96,7 @@ describe Issuable do
...
@@ -95,6 +96,7 @@ describe Issuable do
let!
(
:searchable_issue
)
do
let!
(
:searchable_issue
)
do
create
(
:issue
,
title:
"Searchable awesome issue"
,
description:
'Many cute kittens'
)
create
(
:issue
,
title:
"Searchable awesome issue"
,
description:
'Many cute kittens'
)
end
end
let!
(
:searchable_issue2
)
{
create
(
:issue
,
title:
"Aw"
,
description:
"Cu"
)
}
it
'returns issues with a matching title'
do
it
'returns issues with a matching title'
do
expect
(
issuable_class
.
full_search
(
searchable_issue
.
title
))
expect
(
issuable_class
.
full_search
(
searchable_issue
.
title
))
...
@@ -133,8 +135,8 @@ describe Issuable do
...
@@ -133,8 +135,8 @@ describe Issuable do
expect
(
issuable_class
.
full_search
(
'many kittens'
)).
to
eq
([
searchable_issue
])
expect
(
issuable_class
.
full_search
(
'many kittens'
)).
to
eq
([
searchable_issue
])
end
end
it
'returns
all issues with
a query shorter than 3 chars'
do
it
'returns
issues with a matching description for
a query shorter than 3 chars'
do
expect
(
issuable_class
.
search
(
'zz'
)).
to
eq
(
issuable_class
.
all
)
expect
(
issuable_class
.
full_search
(
searchable_issue2
.
description
.
downcase
)).
to
eq
([
searchable_issue2
]
)
end
end
end
end
...
...
spec/models/snippet_spec.rb
View file @
da42dfb3
...
@@ -88,7 +88,7 @@ describe Snippet do
...
@@ -88,7 +88,7 @@ describe Snippet do
end
end
describe
'.search'
do
describe
'.search'
do
let
(
:snippet
)
{
create
(
:snippet
)
}
let
(
:snippet
)
{
create
(
:snippet
,
title:
'test snippet'
)
}
it
'returns snippets with a matching title'
do
it
'returns snippets with a matching title'
do
expect
(
described_class
.
search
(
snippet
.
title
)).
to
eq
([
snippet
])
expect
(
described_class
.
search
(
snippet
.
title
)).
to
eq
([
snippet
])
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment