Class: ElasticGraph::GraphQL::Filtering::RangeQuery

Inherits:
Object
  • Object
show all
Defined in:
lib/elastic_graph/graphql/filtering/range_query.rb

Overview

Alternate ‘BooleanQuery` implementation for range queries. When we get a filter like this:

{some_field: {gt: 10, lt: 100}}

…we independently build a range query for each predicate. The datastore query structure would look like this:

{filter: [
  {range: {some_field: {gt: 10}}},
  {range: {some_field: {lt: 100}}}
]}

However, the ‘range` query allows these be combined, like so:

{filter: [
  {range: {some_field: {gt: 10, lt: 100}}}
]}

While we haven’t measured it, it’s likely to be more efficient (certainly not less efficient!), and it’s essential that we combine them when we are using ‘any_satisfy`. Consider this filter:

{some_field: {any_satisfy: {gt: 10, lt: 100}}}

This should match a document with ‘some_field: [5, 45, 200]` (since 45 is between 10 and 100), and not match a document with `some_field: [5, 200]` (since `some_field` has no value between 10 and 100). However, if we keep the range clauses separate, this document would match, because `some_field` has a value > 10 and a value < 100 (even though no single value satisfies both parts!). When we combine the clauses into a single `range` query then the filtering works like we expect.

Instance Method Summary collapse

Instance Method Details

#merge_into(bool_node) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/elastic_graph/graphql/filtering/range_query.rb', line 42

def merge_into(bool_node)
  existing_range_index = bool_node[:filter].find_index { |clause| clause.dig(:range, field_name) }
  new_range_clause = {range: {field_name => {operator => value}}}

  if existing_range_index
    existing_range_clause = bool_node[:filter][existing_range_index]
    bool_node[:filter][existing_range_index] = Support::HashUtil.deep_merge(existing_range_clause, new_range_clause)
  else
    bool_node[:filter] << new_range_clause
  end
end