Skip to content

Commit

Permalink
Use lucene query parser for search within user-created browse categories
Browse files Browse the repository at this point in the history
  • Loading branch information
marlo-longley committed Jan 19, 2024
1 parent 4272789 commit 3028d96
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 23 deletions.
11 changes: 10 additions & 1 deletion app/models/concerns/spotlight/browse_category_search_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,21 @@ def fix_up_browse_category_queries(solr_params)

solr_params.append_query(query) if query.present?

# for a browse category formed from a saved search, the query syntax reads as two "must" values
# e.g. "json"=>{"query"=>{"bool"=>{"must"=>["savedsearchterm", "browsecategorysearchterm"]}}}}
must_values = solr_params.dig(:json, :query, :bool, :must)

return unless must_values&.any?

# this type of query must be parsed by lucene to function
solr_params[:defType] = 'lucene'

# This replicates existing spotlight 2.x search behavior, more or less. It
# doesn't take into account the possibility that the browse category query
# could use a different search field (which.. doesn't have an existing UI
# control.. and may require additional upstream work to properly encapsulate
# the two query parameters)
solr_params.dig(:json, :query, :bool, :must)&.map! do |q|
must_values.map! do |q|
q.is_a?(String) ? { edismax: { query: q } } : q
end
end
Expand Down
12 changes: 12 additions & 0 deletions spec/factories/searches.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,16 @@

after(:build) { |search| search.thumbnail = FactoryBot.create(:featured_image) }
end

factory :search_field_search, class: 'Spotlight::Search' do
exhibit
title { 'Based on a search field' }
query_params { { 'search_field' => 'search', 'q' => 'model' } }
end

factory :facet_search, class: 'Spotlight::Search' do
exhibit
title { 'Based on a facet' }
query_params { { 'f' => { 'language_ssim' => 'Latin' } } }
end
end
26 changes: 26 additions & 0 deletions spec/features/browse_category_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,30 @@
expect(page).to have_css "meta[property='og:title'][content='#{search.title}']", visible: false
end
end

context 'with a search field based browse category' do
let(:search) { FactoryBot.create(:search_field_search, title: 'Search field search', exhibit: exhibit, published: true, search_box: true) }

it 'conducts a search within the browse category' do
visit spotlight.exhibit_browse_path(exhibit, search)
expect(search.documents.count).to eq 6

fill_in 'Search within this browse category', with: 'azimuthal'
click_button 'Search within browse category'
expect(page).to have_text('Your search matched 1 of 6 items in this browse category.')
end
end

context 'with a facet based browse category' do
let(:search) { FactoryBot.create(:facet_search, title: 'Facet search', exhibit: exhibit, published: true, search_box: true) }

it 'conducts a search within the browse category' do
visit spotlight.exhibit_browse_path(exhibit, search)
expect(search.documents.count).to eq 3

fill_in 'Search within this browse category', with: 'Stopendael'
click_button 'Search within browse category'
expect(page).to have_text('Your search matched 1 of 3 items in this browse category.')
end
end
end
72 changes: 50 additions & 22 deletions spec/models/spotlight/browse_category_search_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,65 @@ class BrowseCategoryMockSearchBuilder < Blacklight::SearchBuilder
end
let(:solr_request) { Blacklight::Solr::Request.new }
let(:blacklight_params) { { browse_category_id: search.id } }
let(:search) { FactoryBot.create(:search, exhibit: exhibit, query_params: { sort: 'type', f: { genre_ssim: ['term'] }, q: 'search query' }) }

describe '#restrict_to_browse_category' do
it 'adds the search query parameters from the browse category' do
params = subject.to_hash.with_indifferent_access
context 'with a facet as the basis of the browse category (no search query present)' do
let(:search) { FactoryBot.create(:search, exhibit: exhibit, query_params: { sort: 'type', f: { genre_ssim: ['genre facet'] } }) }

expect(params).to include(
q: 'search query',
fq: ['{!term f=genre_ssim}term'],
sort: 'sort_type_ssi asc'
)
describe 'constructs params properly' do
it 'adds facet to the solr params' do
params = subject.to_hash.with_indifferent_access

expect(params).to include(
fq: ['{!term f=genre_ssim}genre facet'],
sort: 'sort_type_ssi asc'
)
end

it 'does not override the default query parser' do
params = subject.to_hash.with_indifferent_access
expect(params).not_to include(:defType)
end
end
end

context 'with a user-provided query' do
let(:blacklight_params) { { browse_category_id: search.id, q: 'cats' } }
context 'with a search query as part of the construction of the browse category' do
let(:search) { FactoryBot.create(:search, exhibit: exhibit, query_params: { sort: 'type', f: { genre_ssim: ['term'] }, q: 'search query' }) }

it 'uses the user-provided query to further restrict the search' do
describe 'constructs params properly' do
it 'includes the facet and the seach term information in the params' do
params = subject.to_hash.with_indifferent_access
expect(params).not_to include(:q)

expect(params).to include(
json: {
query: {
bool: {
must: [
{ edismax: { query: 'search query' } },
{ edismax: { query: 'cats' } }
]
q: 'search query',
fq: ['{!term f=genre_ssim}term'],
sort: 'sort_type_ssi asc'
)
end

context 'with a search term present' do
let(:blacklight_params) { { browse_category_id: search.id, q: 'cats' } }

it 'manipulates the solr query as expected into json syntax' do
params = subject.to_hash.with_indifferent_access
expect(params).not_to include(:q)
expect(params).to include(
json: {
query: {
bool: {
must: [
{ edismax: { query: 'search query' } },
{ edismax: { query: 'cats' } }
]
}
}
}
}
)
)
end

it 'overrides the default query parser' do
params = subject.to_hash.with_indifferent_access
expect(params).to include(defType: 'lucene')
end
end
end
end
Expand Down

0 comments on commit 3028d96

Please sign in to comment.