Commit d5724995 authored by Etienne Baqué's avatar Etienne Baqué

Merge branch 'use-full-text-search-graphql' into 'master'

Use full-text search in issues API / GraphQL

See merge request gitlab-org/gitlab!81980
parents f1279212 c81083f9
......@@ -117,10 +117,6 @@ module IssuableCollections
options[:attempt_group_search_optimizations] = true
end
if collection_type == 'Issue' && Feature.enabled?(:issues_full_text_search, @project || @group, default_enabled: :yaml)
options[:attempt_full_text_search] = true
end
params.permit(finder_type.valid_params).merge(options)
end
end
......
......@@ -37,7 +37,6 @@
# attempt_project_search_optimizations: boolean
# crm_contact_id: integer
# crm_organization_id: integer
# attempt_full_text_search: boolean
#
class IssuableFinder
prepend FinderWithCrossProjectAccess
......@@ -346,7 +345,10 @@ class IssuableFinder
# rubocop: enable CodeReuse/ActiveRecord
def use_full_text_search?
params[:attempt_full_text_search] && params[:search] =~ FULL_TEXT_SEARCH_TERM_REGEX
params[:in].blank? &&
klass.try(:pg_full_text_searchable_columns).present? &&
params[:search] =~ FULL_TEXT_SEARCH_TERM_REGEX &&
Feature.enabled?(:issues_full_text_search, params.project || params.group, default_enabled: :yaml)
end
# rubocop: disable CodeReuse/ActiveRecord
......
......@@ -73,11 +73,11 @@ RSpec.describe Boards::IssuesController do
end
context 'with search param' do
it 'returns matching issues using optimized search' do
it 'returns matching issues' do
create(:labeled_issue, project: project_1, labels: [planning], title: 'Test Issue')
create(:labeled_issue, project: project_1, labels: [planning], title: 'Sample Issue')
list_issues user: user, board: board, list: list1, search: 'Te'
list_issues user: user, board: board, list: list1, search: 'test'
expect(response).to match_response_schema('issues')
expect(json_response['issues'].length).to eq 1
......
......@@ -218,6 +218,10 @@ RSpec.describe Boards::Issues::ListService, services: true do
end
context 'when search param is present' do
before do
stub_feature_flags(issues_full_text_search: false)
end
it 'returns correct issues' do
params = { board_id: board.id, search: 'Iss' }
......
......@@ -144,7 +144,7 @@ module Gitlab
def params_include_filters?
non_filtering_params = %i[
scope state sort group_id include_subgroups
attempt_group_search_optimizations attempt_full_text_search non_archived issue_types
attempt_group_search_optimizations non_archived issue_types
]
finder.params.except(*non_filtering_params).values.any?
......
......@@ -588,10 +588,37 @@ RSpec.describe IssuesFinder do
end
context 'filtering by issue term' do
let(:params) { { search: 'git' } }
let(:params) { { search: search_term } }
it 'returns issues with title and description match for search term' do
expect(issues).to contain_exactly(issue1, issue2)
let_it_be(:english) { create(:issue, project: project1, title: 'title', description: 'something english') }
let_it_be(:japanese) { create(:issue, project: project1, title: '日本語 title', description: 'another english description') }
context 'with latin search term' do
let(:search_term) { 'title english' }
it 'returns matching issues' do
expect(issues).to contain_exactly(english, japanese)
end
end
context 'with non-latin search term' do
let(:search_term) { '日本語' }
it 'returns matching issues' do
expect(issues).to contain_exactly(japanese)
end
end
context 'when full-text search is disabled' do
let(:search_term) { 'somet' }
before do
stub_feature_flags(issues_full_text_search: false)
end
it 'allows partial word matches' do
expect(issues).to contain_exactly(english)
end
end
context 'with anonymous user' do
......@@ -632,29 +659,6 @@ RSpec.describe IssuesFinder do
end
end
context 'filtering by issue term using full-text search' do
let(:params) { { search: search_term, attempt_full_text_search: true } }
let_it_be(:english) { create(:issue, project: project1, title: 'title', description: 'something english') }
let_it_be(:japanese) { create(:issue, project: project1, title: '日本語 title', description: 'another english description') }
context 'with latin search term' do
let(:search_term) { 'title english' }
it 'returns matching issues' do
expect(issues).to contain_exactly(english, japanese)
end
end
context 'with non-latin search term' do
let(:search_term) { '日本語' }
it 'returns matching issues' do
expect(issues).to contain_exactly(japanese)
end
end
end
context 'filtering by issues iids' do
let(:params) { { iids: [issue3.iid] } }
......@@ -1280,7 +1284,7 @@ RSpec.describe IssuesFinder do
end
context 'when the force_cte param is falsey' do
let(:params) { { search: 'foo' } }
let(:params) { { search: '日本語' } }
it 'returns false' do
expect(finder.use_cte_for_search?).to be_falsey
......@@ -1288,7 +1292,7 @@ RSpec.describe IssuesFinder do
end
context 'when a non-simple sort is given' do
let(:params) { { search: 'foo', attempt_project_search_optimizations: true, sort: 'popularity' } }
let(:params) { { search: '日本語', attempt_project_search_optimizations: true, sort: 'popularity' } }
it 'returns false' do
expect(finder.use_cte_for_search?).to be_falsey
......@@ -1297,7 +1301,7 @@ RSpec.describe IssuesFinder do
context 'when all conditions are met' do
context "uses group search optimization" do
let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
let(:params) { { search: '日本語', attempt_group_search_optimizations: true } }
it 'returns true' do
expect(finder.use_cte_for_search?).to be_truthy
......@@ -1306,7 +1310,7 @@ RSpec.describe IssuesFinder do
end
context "uses project search optimization" do
let(:params) { { search: 'foo', attempt_project_search_optimizations: true } }
let(:params) { { search: '日本語', attempt_project_search_optimizations: true } }
it 'returns true' do
expect(finder.use_cte_for_search?).to be_truthy
......@@ -1315,7 +1319,7 @@ RSpec.describe IssuesFinder do
end
context 'with simple sort' do
let(:params) { { search: 'foo', attempt_project_search_optimizations: true, sort: 'updated_desc' } }
let(:params) { { search: '日本語', attempt_project_search_optimizations: true, sort: 'updated_desc' } }
it 'returns true' do
expect(finder.use_cte_for_search?).to be_truthy
......@@ -1324,7 +1328,7 @@ RSpec.describe IssuesFinder do
end
context 'with simple sort as a symbol' do
let(:params) { { search: 'foo', attempt_project_search_optimizations: true, sort: :updated_desc } }
let(:params) { { search: '日本語', attempt_project_search_optimizations: true, sort: :updated_desc } }
it 'returns true' do
expect(finder.use_cte_for_search?).to be_truthy
......
......@@ -58,17 +58,17 @@ RSpec.describe 'search/_results' do
context 'rendering all types of search results' do
let_it_be(:project) { create(:project, :repository, :wiki_repo) }
let_it_be(:issue) { create(:issue, project: project, title: '*') }
let_it_be(:merge_request) { create(:merge_request, title: '*', source_project: project, target_project: project) }
let_it_be(:milestone) { create(:milestone, title: '*', project: project) }
let_it_be(:note) { create(:discussion_note_on_issue, project: project, note: '*') }
let_it_be(:wiki_blob) { create(:wiki_page, wiki: project.wiki, content: '*') }
let_it_be(:issue) { create(:issue, project: project, title: 'testing') }
let_it_be(:merge_request) { create(:merge_request, title: 'testing', source_project: project, target_project: project) }
let_it_be(:milestone) { create(:milestone, title: 'testing', project: project) }
let_it_be(:note) { create(:discussion_note_on_issue, project: project, note: 'testing') }
let_it_be(:wiki_blob) { create(:wiki_page, wiki: project.wiki, content: 'testing') }
let_it_be(:user) { create(:admin) }
%w[issues merge_requests].each do |search_scope|
context "when scope is #{search_scope}" do
let(:scope) { search_scope }
let(:search_objects) { Gitlab::ProjectSearchResults.new(user, '*', project: project).objects(scope) }
let(:search_objects) { Gitlab::ProjectSearchResults.new(user, 'testing', project: project).objects(scope) }
context 'when admin mode is enabled', :enable_admin_mode do
it 'renders the click text event tracking attributes' do
......@@ -99,7 +99,7 @@ RSpec.describe 'search/_results' do
%w[blobs notes wiki_blobs milestones].each do |search_scope|
context "when scope is #{search_scope}" do
let(:scope) { search_scope }
let(:search_objects) { Gitlab::ProjectSearchResults.new(user, '*', project: project).objects(scope) }
let(:search_objects) { Gitlab::ProjectSearchResults.new(user, 'testing', project: project).objects(scope) }
context 'when admin mode is enabled', :enable_admin_mode do
it 'renders the click text event tracking attributes' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment