diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index b424ca4..573844c 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -59,6 +59,9 @@ def record_id(id:, index:) 'you with one for your specific use case' argument :source, String, required: false, default_value: 'All', deprecation_reason: 'Use `sourceFilter`' + argument :boolean_type, String, required: false, default_value: 'OR', + description: 'How to join multiword queries. Defaults to "OR" which means any ' \ + 'of the words much match. Options include: "OR", "AND"' # applied filters argument :access_to_files_filter, [String], @@ -96,9 +99,9 @@ def record_id(id:, index:) end def search(searchterm:, citation:, contributors:, funding_information:, geodistance:, geobox:, identifiers:, - locations:, subjects:, title:, index:, source:, from:, **filters) + locations:, subjects:, title:, index:, source:, from:, boolean_type:, **filters) query = construct_query(searchterm, citation, contributors, funding_information, geodistance, geobox, identifiers, - locations, subjects, title, source, filters) + locations, subjects, title, source, boolean_type, filters) results = Opensearch.new.search(from, query, Timdex::OSClient, highlight_requested?, index) @@ -128,9 +131,10 @@ def inject_hits_fields_into_source(hits) end def construct_query(searchterm, citation, contributors, funding_information, geodistance, geobox, identifiers, - locations, subjects, title, source, filters) + locations, subjects, title, source, boolean_type, filters) query = {} query[:q] = searchterm + query[:boolean_type] = boolean_type query[:citation] = citation query[:contributors] = contributors query[:funding_information] = funding_information diff --git a/app/models/opensearch.rb b/app/models/opensearch.rb index 48b97be..996def4 100644 --- a/app/models/opensearch.rb +++ b/app/models/opensearch.rb @@ -105,6 +105,33 @@ def multisearch ] end + # https://opensearch.org/docs/latest/query-dsl/minimum-should-match/#valid-values + # checks for preconfigured cases or uses whatever is supplied (i.e. we currently accept OpenSearch syntax for + # minimum_should_match) + def minimum_should_match + case @params[:boolean_type] + when 'OR' + '0%' + when 'AND' + '100%' + # 5 or less terms match all (AND) + # More than 5 match all but one + when 'experiment_a' + '4<100% 5<-1' + # 4 or less terms match all (AND) + # More than 4 match all but one + when 'experiment_b' + '3<100% 4<-1' + # 4 or less terms match all (AND) + # 5 to 10 match all but one + # 10 or more match 90% + when 'experiment_c' + '3<100% 9<-1 10<90%' + else + @params[:boolean_type] + end + end + def matches m = [] if @params[:q].present? @@ -113,7 +140,8 @@ def matches query: @params[:q].downcase, fields: ['alternate_titles', 'call_numbers', 'citation', 'contents', 'contributors.value', 'dates.value', 'edition', 'funding_information.*', 'identifiers.value', 'languages', 'locations.value', - 'notes.value', 'numbering', 'publication_information', 'subjects.value', 'summary', 'title'] + 'notes.value', 'numbering', 'publication_information', 'subjects.value', 'summary', 'title'], + minimum_should_match: } } end