Skip to content

Commit

Permalink
Merge pull request #534 from MITLibraries/rdi-170-searching-multiple-…
Browse files Browse the repository at this point in the history
…sources

OpenSearch and GraphQL for multiple source filters
  • Loading branch information
JPrevost authored Jul 7, 2022
2 parents 491dd89 + 00a3f15 commit 99da08a
Show file tree
Hide file tree
Showing 6 changed files with 356 additions and 6 deletions.
2 changes: 1 addition & 1 deletion app/graphql/types/query_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def record_id(id:)
argument :format_facet, [String], required: false, default_value: nil
argument :languages_facet, [String], required: false, default_value: nil
argument :literary_form_facet, String, required: false, default_value: nil
argument :source_facet, String, required: false, default_value: 'All'
argument :source_facet, [String], required: false, default_value: nil
argument :subjects_facet, [String], required: false, default_value: nil
end
else
Expand Down
25 changes: 23 additions & 2 deletions app/models/opensearch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Opensearch

def search(from, params, client)
@params = params
client.search(index: ENV['ELASTICSEARCH_INDEX'],
client.search(index: ENV.fetch('ELASTICSEARCH_INDEX', nil),
body: build_query(from))
end

Expand Down Expand Up @@ -114,7 +114,8 @@ def filters

f.push filter_single(@params[:literary_form_facet], 'literary_form') if @params[:literary_form_facet]

f.push filter_single(@params[:source_facet], 'source') if @params[:source_facet]
f.push filter_sources(@params[:source_facet]) if @params[:source_facet]

f.push filter(@params[:subjects_facet], 'subjects') if @params[:subjects_facet]
f
end
Expand Down Expand Up @@ -155,6 +156,26 @@ def filter_single(param, field)
}
end

def filter_sources(param)
{
bool: {
should: source_array(param)
}
}
end

def source_array(param)
sources = []
param.each do |source|
sources << {
term: {
source: source
}
}
end
sources
end

# https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html
def aggregations
{
Expand Down
98 changes: 98 additions & 0 deletions test/controllers/graphql_controller_v2_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -314,4 +314,102 @@ def setup
json = JSON.parse(response.body)
assert(json['errors'].first['message'].present?)
end

test 'graphqlv2 filter multiple sources' do
VCR.use_cassette('graphql v2 filter multiple sources') do

# no filters to return all sources. used later to test filters return less than the total.
post '/graphql', params: { query:
'{
search(searchterm: "data") {
hits
aggregations {
source {
key
docCount
}
}
}
}'
}

json = JSON.parse(response.body)
initial_source_array = json['data']['search']['aggregations']['source']

# filtering to 2 sources returns 2 sources
post '/graphql', params: { query:
'{
search(searchterm: "data", sourceFacet: ["Zenodo", "DSpace@MIT"]) {
hits
aggregations {
source {
key
docCount
}
}
}
}'
}
assert_equal(200, response.status)

json = JSON.parse(response.body)
filtered_source_array = json['data']['search']['aggregations']['source']

assert(initial_source_array.count > filtered_source_array.count)
assert_equal(2, filtered_source_array.count)

expected_sources = ['zenodo', 'dspace@mit']
actual_sources = filtered_source_array.map{|source| source["key"]}
assert_equal(expected_sources, actual_sources)
end
end

test 'graphqlv2 filter single source' do
VCR.use_cassette('graphql v2 filter single source') do

# no filters to return all sources. used later to test filters return less than the total.
post '/graphql', params: { query:
'{
search(searchterm: "data") {
hits
aggregations {
source {
key
docCount
}
}
}
}'
}

json = JSON.parse(response.body)
initial_source_array = json['data']['search']['aggregations']['source']

# filtering to 1 sources returns 1 source
post '/graphql', params: { query:
'{
search(searchterm: "data", sourceFacet: ["DSpace@MIT"]) {
hits
aggregations {
source {
key
docCount
}
}
}
}'
}
assert_equal(200, response.status)

json = JSON.parse(response.body)
filtered_source_array = json['data']['search']['aggregations']['source']

assert(initial_source_array.count > filtered_source_array.count)
assert_equal(1, filtered_source_array.count)

expected_sources = ['dspace@mit']
actual_sources = filtered_source_array.map{|source| source["key"]}
assert_equal(expected_sources, actual_sources)
end
end
end
21 changes: 18 additions & 3 deletions test/models/opensearch_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,32 @@ class OpensearchTest < ActiveSupport::TestCase
VCR.use_cassette('opensearch single field nested') do
params = { contributors: 'mcternan' }
results = Opensearch.new.search(0, params, Timdex::OSClient)
assert_equal "A common table : 80 recipes and stories from my shared cultures /",
assert_equal 'A common table : 80 recipes and stories from my shared cultures /',
results['hits']['hits'].first['_source']['title']
end
end

test 'searches multiple fields' do
VCR.use_cassette('opensearch multiple fields') do
params = { q: 'chinese', title: 'common', contributors: 'mcternan'}
params = { q: 'chinese', title: 'common', contributors: 'mcternan' }
results = Opensearch.new.search(0, params, Timdex::OSClient)
assert_equal "A common table : 80 recipes and stories from my shared cultures /",
assert_equal 'A common table : 80 recipes and stories from my shared cultures /',
results['hits']['hits'].first['_source']['title']
end
end

test 'source_array creates correct query structure' do
sources = ['Zenodo', 'DSpace@MIT']
expected = [{ term: { source: 'Zenodo' } }, { term: { source: 'DSpace@MIT' } }]

assert_equal(expected, Opensearch.new.source_array(sources))
end

test 'filter_sources creates correct query structure' do
sources = ['Zenodo', 'DSpace@MIT']
expected = { bool: { should: [{ term: { source: 'Zenodo' } },
{ term: { source: 'DSpace@MIT' } }] } }

assert_equal(expected, Opensearch.new.filter_sources(sources))
end
end
108 changes: 108 additions & 0 deletions test/vcr_cassettes/graphql_v2_filter_multiple_sources.yml

Large diffs are not rendered by default.

108 changes: 108 additions & 0 deletions test/vcr_cassettes/graphql_v2_filter_single_source.yml

Large diffs are not rendered by default.

0 comments on commit 99da08a

Please sign in to comment.