Releases: block/elasticgraph
v0.19.0.0
ElasticGraph v0.19.0.0 has been released! This release includes a change to how we treat empty filter predicates, a number of other bug fixes, and many other small changes.
Changes to Treatment of Empty Filter Predicate
ElasticGraph's filtering API supports what we call empty predicates. An empty predicate is one which contains no information. This can take many forms:
field: null
field: {}
field: {gt: null}
field: {subfield: {}}
field: {subfield: {equalToAnyOf: null}}
Most of the time, empty predicates show up when using a query with variables. Here's an example:
query FindArtists(
$names: [String!] = null
$yearFormed_gt: Int = null
$albumNames: [String!] = null
) {
artists(filter: {
name: {equalToAnyOf: $names}
bio: {yearFormed: {gt: $yearFormed_gt}}
albums: {anySatisfy: {name: {equalToAnyOf: $albumNames}}}
}) {
nodes {
name
bio {
yearFormed
}
albums {
name
}
}
}
}
This query supports optional filtering using the nullable variables $names
, $yearFormed_gt
, and $albumNames
. Any of these variables that are submitted as null
or omitted when submitting the query will result in an empty predicate.
In prior ElasticGraph versions, empty predicates were ignored. Internally, they were pruned out. For example, if a client submitted the above query with {"yearFormed_gt": 2000}
, then ElasticGraph would evaluate the query as if it was this:
query FindArtists(
$yearFormed_gt: Int = null
) {
artists(filter: {
bio: {yearFormed: {gt: $yearFormed_gt}}
}) {
nodes {
name
bio {
yearFormed
}
albums {
name
}
}
}
}
While this generally worked great, we realized that this treatment breaks some standard boolean algebra laws when an empty predicate shows up inside an anyOf
or a not
(as detailed in sections below). In ElasticGraph v0.19.0.0, we now treat empty predicates as matching all documents rather than ignoring them outright. In SQL terms, an empty predicate has the value of TRUE
(e.g. WHERE field = "abc" AND TRUE
). Under an anyOf
an empty predicate now acts like an OR TRUE
and under a not
it acts like a NOT TRUE
.
Impact on anyOf
Previously, empty predicates inside an anyOf: [...]
were ignored, leaving only the non-empty predicates. The anyOf
would match documents (or not) based on the remaining non-empty predicates. If all predicates were empty, the anyOf
would be reduced to []
, matching no documents as a result.
This behavior was incorrect; filter: A
and filter: {anyOf: [A]}
must always return the same results, no matter what A
is. With the old behavior, filter: emptyPredicate
would match all documents while filter: {anyOf: [emptyPredicate]}
would match no documents.
The new treatment of empty predicates fixes this: if an anyOf
contains an empty predicate, the anyOf
will now match all documents (since the empty predicate itself matches all documents).
Note: anyOf: null
is not impacted by this--that expression matched all documents before and continues to match all documents in ElasticGraph v0.19.0.0.
Impact on not
Previously, a not: emptyPredicate
expression was ignored. However, according to the laws of boolean algebra, filter: A
and filter: {not: A}
must be complements. Since filter: emptyPredicate
matches all documents, filter: {not: emptyPredicate}
must match no documents. The new treatment fixes this.
Upgrade Process
During the upgrade process, we recommend that you carefully audit your client queries to see which ones may be impacted by this change in behavior. In general, a query can only be impacted when it allows an empty predicate (either via a literal null
or {}
, or via a query variable that could have those values) under anyOf
or not
. Queries which do not use the anyOf
or not
operators will not be impacted, and queries which do not allow an empty predicate in those locations will not be impacted. Any queries which may be impacted by this change should be verified to be compatible with the new semantics, or rewritten to be compatible with it.
Breaking Changes
- Remove
anyOf
andnot
fromMatches(Phrase|Query)FilterInput
. by @myronmarston (in pre-public codebase) - Improved the
indexer_autoscaler_lambda
to manage lambda concurrency instead of SQS event source mapping concurrency to allow it to go past 1000. by @akumar1214 in #13, #14 - Fix filter boolean algebra bugs related to empty predicates under
anyOf
andnot
. by @acerbusace in #8, #22, #6, #39, #40, #41
Bug Fixes
- Fix filter boolean algebra bugs related to empty predicates under
anyOf
andnot
. by @acerbusace in #8, #22, #6, #39, #40, #41 - Validate
variables
to make sure they are a JSON object as expected. by @myronmarston in #42 - Handle
too_many_buckets_exception
more gracefully. by @myronmarston in #44 - Fix
ArgumentError
when grouping sub-aggregations on a nullable field. by @myronmarston (in pre-public codebase)
Dependency Upgrades
- Update officially supported versions of Elasticsearch (8.15.1 -> 8.16.1) and OpenSearch (2.16.0 -> 2.18.0). by @myronmarston in #58, #5
- Support GraphQL gem 2.4. by @myronmarston in #26, #31, #33, #32, #43
- Update lower bounds on a number of other gem dependencies. by @myronmarston in #59, #23
Other Improvements
- Install analysis-icu plugin locally by @zachbutler-squareup in #35
- Improve GraphQL doc accuracy and consistency. by @myronmarston, @acerbusace (in pre-public codebase)
- Various improvements to project website. by @myronmarston, @BrianSigafoos-SQ, @mattcarp21 in #57, #1, #3, #10, #15, #16, #24, #25.
- Other internal refactorings. by @myronmarston in #52, #53, #54, #55, #56
- Other codebase maintenance tasks. by @myronmarston in #45, #47, #50, #49, #60, #4, #12, #20, #18, #19, #28, #34, #36, #37, #38,
New Contributors
- @myronmarston made their first contribution in #1
- @BrianSigafoos-SQ made their first contribution in #10
- @acerbusace made their first contribution in #8
- @mattcarp21 made their first contribution in #25
- @akumar1214 made their first contribution in #13
- @zachbutler-squareup made their first contribution in #35
Full Changelog: https://github.com/block/elasticgraph/commits/v0.19.0.0
v0.19.0.0.rc2
What's Changed
- Fix github pages site to use proper relative links. by @myronmarston in #1
- Update project links. by @myronmarston in #3
- Upgrade actions/setup-node from v3 to v4. by @myronmarston in #4
- Build against latest Elasticsearch and OpenSearch. by @myronmarston in #5
- Fix CODEOWNERS so that @BrianSigafoos-SQ and I are both owners. by @myronmarston in #12
- Update site homepage by @BrianSigafoos-SQ in #10
- Treat nil values as empty predicate by @acerbusace in #8
- Fix schema on getting started page; Extract tagline by @BrianSigafoos-SQ in #15
- Update site success story metrics by @BrianSigafoos-SQ in #16
- Move GraphiQL license attribution into README. by @myronmarston in #20
- Provide a summary status of the CI build that we can block merges on. by @myronmarston in #18
- Deal with rackup 2.2 release. by @myronmarston in #23
- Add badges to the README. by @myronmarston in #19
- Interpret field_or_op before sub_expression by @acerbusace in #22
- Tweak site text by @BrianSigafoos-SQ in #24
- Update the FullTextSearch docs to provide an example of their optionality by @mattcarp21 in #25
- Prepare test suite for for v2.4 of the GraphQL gem. by @myronmarston in #26
- Update discord link. by @myronmarston in #28
- Change anyOf behaviour to evaluate to true for empty predicates by @acerbusace in #6
- Refactor: simplify and optimize
ElasticGraph::GraphQL::Schema
. by @myronmarston in #31 - Upgrade GraphQL gem to
~> 2.4.3
. by @myronmarston in #32 - Restore
GraphQL::Schema#defined_types
. by @myronmarston in #33 - [indexer_autoscaler_lambda] tune Lambda reserved concurrency instead of ESM concurrency by @akumar1214 in #13
- [indexer_autoscaler_lambda] pause indexing if the available storage drops below a threshold by @akumar1214 in #14
- Update
CODE_OF_CONDUCT.md
andGOVERNANCE.md
. by @myronmarston in #34 - Flesh out
CONTRIBUTING.md
. by @myronmarston in #36 - Increase default docker
daemon_timeout
. by @myronmarston in #37 - Increase the local boot daemon timeout to 5 minutes. by @myronmarston in #38
- Install analysis-icu plugin locally by @zachbutler-squareup in #35
- Treat anyOf: [] as matching no routing shards by @acerbusace in #39
- Rewrite documentation for empty filters/predicates by @acerbusace in #40
- Change
NullOrEmptyFilters
toEmptyFilters
to match file name. by @myronmarston in #41 - Validate
variables
to make sure they are a JSON object as expected. by @myronmarston in #42 - Upgrade GraphQL gem to 2.4.5 and deal with eager loading. by @myronmarston in #43
- Handle
too_many_buckets_exception
more gracefully. by @myronmarston in #44
New Contributors
- @myronmarston made their first contribution in #1
- @BrianSigafoos-SQ made their first contribution in #10
- @acerbusace made their first contribution in #8
- @mattcarp21 made their first contribution in #25
- @akumar1214 made their first contribution in #13
- @zachbutler-squareup made their first contribution in #35
Full Changelog: https://github.com/block/elasticgraph/commits/v0.19.0.0.rc2