Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treat nil values as empty predicate #8

Merged
merged 1 commit into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@ def to_s

def process_filter_hash(bool_node, filter_hash, field_path)
filter_hash.each do |field_or_op, expression|
# `nil` filter predicates should be ignored, so we can safely `compact` them out.
# It also is simpler to handle them once here instead of the different branches
# below having to be aware of possible `nil` predicates.
expression = expression.compact if expression.is_a?(::Hash)

case filter_node_interpreter.identify_node_type(field_or_op, expression)
when :empty
# This is an "empty" filter predicate and we can ignore it.
Expand Down Expand Up @@ -313,7 +308,7 @@ def process_list_count_expression(bool_node, expression, field_path)
# While we index an explicit count of 0, the count field will be missing from documents indexed before
# the list field was defined on the ElasticGraph schema. To properly match those documents, we need to
# convert this into an OR (using `any_of`) to also match documents that lack the field entirely.
unless excludes_zero?(expression)
if filters_to_range_including_zero?(expression)
expression = {schema_names.any_of => [
expression,
{schema_names.equal_to_any_of => [nil]}
Expand All @@ -337,20 +332,28 @@ def build_bool_hash(&block)
{bool: bool_node}
end

# Determines if the given filter expression excludes the value `0`.
def excludes_zero?(expression)
expression.any? do |operator, operand|
case operator
when schema_names.equal_to_any_of then !operand.include?(0)
when schema_names.lt then operand <= 0
when schema_names.lte then operand < 0
when schema_names.gt then operand >= 0
when schema_names.gte then operand > 0
else
# :nocov: -- all operators are covered above. But simplecov complains about an implicit `else` branch being uncovered, so here we've defined it to wrap it with `:nocov:`.
false
# :nocov:
end
# Determines if the given expression filters to a range that includes `0`.
# If it does not do any filtering (e.g. an empty expression) it will return `false`.
def filters_to_range_including_zero?(expression)
expression = expression.compact

expression.size > 0 && expression.none? do |operator, operand|
operator_excludes_zero?(operator, operand)
end
end

# Determines if the given operator and operand exclude 0 as a matched value.
def operator_excludes_zero?(operator, operand)
case operator
when schema_names.equal_to_any_of then !operand.include?(0)
when schema_names.lt then operand <= 0
when schema_names.lte then operand < 0
when schema_names.gt then operand >= 0
when schema_names.gte then operand > 0
else
# :nocov: -- all operators are covered above. But simplecov complains about an implicit `else` branch being uncovered, so here we've defined it to wrap it with `:nocov:`.
false
# :nocov:
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ module ElasticGraph
def process_sub_field_expression: (stringOrSymbolHash, stringHash, FieldPath) -> void
def process_list_count_expression: (stringOrSymbolHash, stringHash, FieldPath) -> void
def build_bool_hash: () { (stringOrSymbolHash) -> void } -> stringOrSymbolHash?
def excludes_zero?: (stringHash) -> bool
def filters_to_range_including_zero?: (stringHash) -> bool
def operator_excludes_zero?: (::String, untyped) -> bool
def required_matching_clause_count: (stringOrSymbolHash) -> ::Integer
end
end
Expand Down