Class: SearchResolver
- Inherits:
-
Object
- Object
- SearchResolver
- Defined in:
- backend/app/model/search_resolver.rb
Defined Under Namespace
Classes: PassThroughResolver, ResolveDefinition
Constant Summary collapse
- MAX_BOOLEAN_QUERIES =
Theoretically someone might resolve a field that matches an unbounded number of records, and this could cause an OOM. Set an upper bound.
AppConfig[:max_boolean_queries]
- MAX_RESOLVE_RESULTS =
AppConfig[:max_page_size] * 2
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(resolve_definitions) ⇒ SearchResolver
constructor
A new instance of SearchResolver.
-
#resolve(results) ⇒ Object
Constructor Details
#initialize(resolve_definitions) ⇒ SearchResolver
Returns a new instance of SearchResolver.
8 9 10 |
# File 'backend/app/model/search_resolver.rb', line 8 def initialize(resolve_definitions) @resolve_definitions = resolve_definitions.map {|s| ResolveDefinition.parse(s)} end |
Class Method Details
.add_custom_resolver(name, resolver_class) ⇒ Object
73 74 75 76 |
# File 'backend/app/model/search_resolver.rb', line 73 def self.add_custom_resolver(name, resolver_class) @custom_resolvers ||= {} @custom_resolvers[name] = resolver_class end |
.resolver_for(name) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 |
# File 'backend/app/model/search_resolver.rb', line 78 def self.resolver_for(name) if name clz = @custom_resolvers.fetch(name) { raise "Unrecognized search resolver: #{name}" } clz.new else PassThroughResolver.new end end |
Instance Method Details
#resolve(results) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'backend/app/model/search_resolver.rb', line 12 def resolve(results) @resolve_definitions.each do |resolve_def| source_field = resolve_def.source_field target_field = resolve_def.target_field custom_resolver = resolve_def.custom_resolver # Build up and run a Solr query to pull back the documents we'll be inlining search_terms = results['results'].map {|doc| doc[source_field]}.compact.flatten unless search_terms.empty? boolean_query = JSONModel.JSONModel(:boolean_query) .from_hash('op' => 'OR', 'subqueries' => search_terms.map {|term| JSONModel.JSONModel(:field_query) .from_hash('field' => target_field, 'value' => term, 'literal' => true) .to_hash }) query = JSONModel.JSONModel(:advanced_query).from_hash('query' => boolean_query) if query['query']['subqueries'].size > MAX_BOOLEAN_QUERIES query['query']['subqueries'] = query['query']['subqueries'].take(MAX_BOOLEAN_QUERIES) Log.warn("Query subqueries hit MAX_BOOLEAN_QUERIES. Result set may be incomplete: #{query.to_hash.inspect}") end resolved_results = Solr.search(Solr::Query.create_advanced_search(query).pagination(1, MAX_RESOLVE_RESULTS)) if resolved_results['total_hits'] > MAX_RESOLVE_RESULTS Log.warn("Resolve query hit MAX_RESOLVE_RESULTS. Result set may be incomplete: #{query.to_hash.inspect}") end # Insert the resolved records into our original result set. results['results'].each do |result| resolved = resolved_results['results'].map {|resolved| key = resolved[target_field] if ASUtils.wrap(result[source_field]).include?(key) {key => [SearchResolver.resolver_for(custom_resolver).resolve(resolved)]} end }.compact # Merge our entries into a single hash keyed on `key` result["_resolved_#{source_field}"] = resolved.reduce {|merged, elt| merged.merge(elt) {|key, coll1, coll2| coll1 + coll2}} end end end end |