elasticgraph-graphql 0.19.1.1 → 0.19.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/lib/elastic_graph/graphql/aggregation/composite_grouping_adapter.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/computation.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/date_histogram_grouping.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/field_path_encoder.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/field_term_grouping.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/key.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/nested_sub_aggregation.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/non_composite_grouping_adapter.rb +2 -2
- data/lib/elastic_graph/graphql/aggregation/path_segment.rb +2 -2
- data/lib/elastic_graph/graphql/aggregation/query.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/query_adapter.rb +33 -6
- data/lib/elastic_graph/graphql/aggregation/query_optimizer.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/resolvers/aggregated_values.rb +2 -6
- data/lib/elastic_graph/graphql/aggregation/resolvers/count_detail.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/resolvers/grouped_by.rb +26 -6
- data/lib/elastic_graph/graphql/aggregation/resolvers/node.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/resolvers/relay_connection_builder.rb +5 -6
- data/lib/elastic_graph/graphql/aggregation/resolvers/sub_aggregations.rb +10 -8
- data/lib/elastic_graph/graphql/aggregation/script_term_grouping.rb +1 -1
- data/lib/elastic_graph/graphql/aggregation/term_grouping.rb +2 -2
- data/lib/elastic_graph/graphql/client.rb +1 -1
- data/lib/elastic_graph/graphql/config.rb +21 -6
- data/lib/elastic_graph/graphql/datastore_query/document_paginator.rb +10 -5
- data/lib/elastic_graph/graphql/datastore_query/index_expression_builder.rb +2 -3
- data/lib/elastic_graph/graphql/datastore_query/paginator.rb +1 -1
- data/lib/elastic_graph/graphql/datastore_query/routing_picker.rb +2 -3
- data/lib/elastic_graph/graphql/datastore_query.rb +66 -74
- data/lib/elastic_graph/graphql/datastore_response/document.rb +1 -1
- data/lib/elastic_graph/graphql/datastore_response/search_response.rb +83 -9
- data/lib/elastic_graph/graphql/datastore_search_router.rb +19 -4
- data/lib/elastic_graph/graphql/decoded_cursor.rb +1 -1
- data/lib/elastic_graph/graphql/filtering/boolean_query.rb +1 -1
- data/lib/elastic_graph/graphql/filtering/field_path.rb +1 -1
- data/lib/elastic_graph/graphql/filtering/filter_args_translator.rb +2 -2
- data/lib/elastic_graph/graphql/filtering/filter_interpreter.rb +10 -5
- data/lib/elastic_graph/graphql/filtering/filter_node_interpreter.rb +2 -2
- data/lib/elastic_graph/graphql/filtering/filter_value_set_extractor.rb +17 -2
- data/lib/elastic_graph/graphql/filtering/range_query.rb +1 -1
- data/lib/elastic_graph/graphql/http_endpoint.rb +2 -2
- data/lib/elastic_graph/graphql/monkey_patches/schema_field.rb +1 -1
- data/lib/elastic_graph/graphql/monkey_patches/schema_object.rb +1 -1
- data/lib/elastic_graph/graphql/query_adapter/filters.rb +1 -1
- data/lib/elastic_graph/graphql/query_adapter/pagination.rb +1 -1
- data/lib/elastic_graph/graphql/query_adapter/requested_fields.rb +18 -3
- data/lib/elastic_graph/graphql/query_adapter/sort.rb +1 -1
- data/lib/elastic_graph/graphql/query_details_tracker.rb +13 -4
- data/lib/elastic_graph/graphql/query_executor.rb +12 -5
- data/lib/elastic_graph/graphql/resolvers/get_record_field_value.rb +6 -12
- data/lib/elastic_graph/graphql/resolvers/graphql_adapter_builder.rb +123 -0
- data/lib/elastic_graph/graphql/resolvers/list_records.rb +4 -4
- data/lib/elastic_graph/graphql/resolvers/nested_relationships.rb +57 -27
- data/lib/elastic_graph/graphql/resolvers/nested_relationships_source.rb +324 -0
- data/lib/elastic_graph/graphql/resolvers/object.rb +36 -0
- data/lib/elastic_graph/graphql/resolvers/query_adapter.rb +2 -2
- data/lib/elastic_graph/graphql/resolvers/query_source.rb +6 -3
- data/lib/elastic_graph/graphql/resolvers/relay_connection/array_adapter.rb +1 -1
- data/lib/elastic_graph/graphql/resolvers/relay_connection/generic_adapter.rb +1 -1
- data/lib/elastic_graph/graphql/resolvers/relay_connection/page_info.rb +1 -1
- data/lib/elastic_graph/graphql/resolvers/relay_connection/search_response_adapter_builder.rb +1 -1
- data/lib/elastic_graph/graphql/resolvers/relay_connection.rb +1 -1
- data/lib/elastic_graph/graphql/resolvers/resolvable_value.rb +2 -7
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/cursor.rb +1 -1
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/date.rb +1 -1
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/date_time.rb +1 -1
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/local_time.rb +1 -1
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/longs.rb +1 -1
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/no_op.rb +1 -1
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/time_zone.rb +1 -1
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/untyped.rb +1 -1
- data/lib/elastic_graph/graphql/scalar_coercion_adapters/valid_time_zones.rb +1 -1
- data/lib/elastic_graph/graphql/schema/arguments.rb +1 -1
- data/lib/elastic_graph/graphql/schema/enum_value.rb +1 -1
- data/lib/elastic_graph/graphql/schema/field.rb +12 -27
- data/lib/elastic_graph/graphql/schema/relation_join.rb +17 -9
- data/lib/elastic_graph/graphql/schema/type.rb +15 -7
- data/lib/elastic_graph/graphql/schema.rb +11 -31
- data/lib/elastic_graph/graphql.rb +38 -40
- data/script/dump_time_zones +1 -1
- metadata +25 -27
- data/lib/elastic_graph/graphql/resolvers/graphql_adapter.rb +0 -114
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c406c0dd4109d2b92b834f989f5819fc6342696b9c0b231f38b0bb4fc0d8f858
|
4
|
+
data.tar.gz: 95b206f183b6ccfc644ffab571e43232be92123d8c0998bd4add03b4d8571404
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a1474ca90d5ec6a4c65996491e3570d3b4fef1bd40c9550b0b850bb663018dd9cd690e262af080212019ab12c05651aeca3f79f22ba1007a676422578e8787e
|
7
|
+
data.tar.gz: 8d7f2aff08c7ea4f6038943682f1231d4371c67003acf2f78321b749d4838550eef4b53df7a37b02ee134a10075e0f382251c06d9d18ce7f8bada9838579f201
|
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -124,7 +124,7 @@ module ElasticGraph
|
|
124
124
|
# a time breaker to ensure deterministic results, but don't particularly care which buckets
|
125
125
|
# come first.
|
126
126
|
[-b.fetch("doc_count"), b.fetch("key_values").map(&:to_s)]
|
127
|
-
end.first(size)
|
127
|
+
end.first(size + 1) # We add 1 so `page_info.has_next_page` detection works.
|
128
128
|
end
|
129
129
|
|
130
130
|
def missing_bucket_path_from(buckets_path)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -22,7 +22,7 @@ module ElasticGraph
|
|
22
22
|
|
23
23
|
new(
|
24
24
|
name_in_graphql_query: ast_node.alias || ast_node.name,
|
25
|
-
name_in_index: field&.name_in_index
|
25
|
+
name_in_index: field&.name_in_index
|
26
26
|
)
|
27
27
|
end
|
28
28
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -24,12 +24,39 @@ module ElasticGraph
|
|
24
24
|
# Responsible for taking in the incoming GraphQL request context, arguments, and the GraphQL
|
25
25
|
# schema and directives and populating the `aggregations` portion of `query`.
|
26
26
|
class QueryAdapter < Support::MemoizableData.define(:schema, :config, :filter_args_translator, :runtime_metadata, :sub_aggregation_grouping_adapter)
|
27
|
+
# Partially applied `QueryAdapter` -- essentially the `QueryAdapter` without the schema,
|
28
|
+
# so that it can be instantiated before the `Schema` instance exists, instead providing it from
|
29
|
+
# `context` at query time.
|
30
|
+
class WithoutSchema
|
31
|
+
def initialize(config:, filter_args_translator:, runtime_metadata:, sub_aggregation_grouping_adapter:)
|
32
|
+
@build_adapter = ->(schema) do
|
33
|
+
QueryAdapter.new(
|
34
|
+
schema: schema,
|
35
|
+
config: config,
|
36
|
+
filter_args_translator: filter_args_translator,
|
37
|
+
runtime_metadata: runtime_metadata,
|
38
|
+
sub_aggregation_grouping_adapter: sub_aggregation_grouping_adapter
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def call(query:, lookahead:, args:, field:, context:)
|
44
|
+
return query unless field.type.unwrap_fully.indexed_aggregation?
|
45
|
+
|
46
|
+
@build_adapter.call(context.fetch(:elastic_graph_schema)).call(
|
47
|
+
query: query,
|
48
|
+
lookahead: lookahead,
|
49
|
+
args: args,
|
50
|
+
field: field,
|
51
|
+
context: context
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
27
56
|
# @dynamic element_names
|
28
57
|
attr_reader :element_names
|
29
58
|
|
30
59
|
def call(query:, lookahead:, args:, field:, context:)
|
31
|
-
return query unless field.type.unwrap_fully.indexed_aggregation?
|
32
|
-
|
33
60
|
aggregations_node = extract_aggregation_node(lookahead, field, context.query)
|
34
61
|
return query unless aggregations_node
|
35
62
|
|
@@ -165,7 +192,7 @@ module ElasticGraph
|
|
165
192
|
|
166
193
|
Aggregation::Computation.new(
|
167
194
|
source_field_path: field_path,
|
168
|
-
computed_index_field_name: computed_field.name_in_index
|
195
|
+
computed_index_field_name: computed_field.name_in_index,
|
169
196
|
detail: computation_detail
|
170
197
|
)
|
171
198
|
end
|
@@ -186,7 +213,7 @@ module ElasticGraph
|
|
186
213
|
elsif !field.type.object?
|
187
214
|
case field.type.name
|
188
215
|
# Legacy date grouping API
|
189
|
-
when
|
216
|
+
when "Date"
|
190
217
|
legacy_date_histogram_groupings_from(
|
191
218
|
field_path: field_path,
|
192
219
|
node: node,
|
@@ -194,7 +221,7 @@ module ElasticGraph
|
|
194
221
|
get_offset: ->(args) { args[element_names.offset_days]&.then { |days| "#{days}d" } }
|
195
222
|
)
|
196
223
|
# Legacy datetime grouping API
|
197
|
-
when
|
224
|
+
when "DateTime"
|
198
225
|
legacy_date_histogram_groupings_from(
|
199
226
|
field_path: field_path,
|
200
227
|
node: node,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -15,17 +15,13 @@ module ElasticGraph
|
|
15
15
|
module Aggregation
|
16
16
|
module Resolvers
|
17
17
|
class AggregatedValues < ::Data.define(:aggregation_name, :bucket, :field_path)
|
18
|
-
def can_resolve?(field:, object:)
|
19
|
-
true
|
20
|
-
end
|
21
|
-
|
22
18
|
def resolve(field:, object:, args:, context:, lookahead:)
|
23
19
|
return with(field_path: field_path + [PathSegment.for(field: field, lookahead: lookahead)]) if field.type.object?
|
24
20
|
|
25
21
|
key = Key::AggregatedValue.new(
|
26
22
|
aggregation_name: aggregation_name,
|
27
23
|
field_path: field_path.map(&:name_in_graphql_query),
|
28
|
-
function_name: field.name_in_index
|
24
|
+
function_name: field.name_in_index
|
29
25
|
)
|
30
26
|
|
31
27
|
result = Support::HashUtil.verbose_fetch(bucket, key.encode)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -14,16 +14,36 @@ module ElasticGraph
|
|
14
14
|
module Aggregation
|
15
15
|
module Resolvers
|
16
16
|
class GroupedBy < ::Data.define(:bucket, :field_path)
|
17
|
-
def can_resolve?(field:, object:)
|
18
|
-
true
|
19
|
-
end
|
20
|
-
|
21
17
|
def resolve(field:, object:, args:, context:, lookahead:)
|
22
18
|
new_field_path = field_path + [PathSegment.for(field: field, lookahead: lookahead)]
|
23
19
|
return with(field_path: new_field_path) if field.type.object?
|
24
20
|
|
25
21
|
bucket_entry = Support::HashUtil.verbose_fetch(bucket, "key")
|
26
|
-
Support::HashUtil.verbose_fetch(bucket_entry, FieldPathEncoder.encode(new_field_path.map(&:name_in_graphql_query)))
|
22
|
+
value = Support::HashUtil.verbose_fetch(bucket_entry, FieldPathEncoder.encode(new_field_path.map(&:name_in_graphql_query)))
|
23
|
+
|
24
|
+
if field.type.unwrap_fully.name == "Boolean"
|
25
|
+
work_around_terms_aggregation_boolean_value(value)
|
26
|
+
else
|
27
|
+
value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# Elasticsearch/OpenSearch generally return `true`/`false` for Boolean fields. However, there's one exception to that[^1]:
|
34
|
+
#
|
35
|
+
# > Aggregations like the terms aggregation use 1 and 0 for the key, and the strings "true" and "false" for the key_as_string.
|
36
|
+
#
|
37
|
+
# Since we get 0/1 in _only_ this one case, we translate it back to false/true here. While a bit hacky, there isn't a widespread
|
38
|
+
# need to handle Booleans like this in other places. It would be nice to apply this logic in the `NonCompositeGroupingAdapter`
|
39
|
+
# (since the `composite` aggregation used by the `CompositeGroupingAdapter` does not suffer from this issue!) but we don't have
|
40
|
+
# ready access to the field type there to know that 0/1 mean false/true.
|
41
|
+
#
|
42
|
+
# [^1]: https://www.elastic.co/guide/en/elasticsearch/reference/8.17/boolean.html
|
43
|
+
def work_around_terms_aggregation_boolean_value(value)
|
44
|
+
return false if value == 0
|
45
|
+
return true if value == 1
|
46
|
+
value
|
27
47
|
end
|
28
48
|
end
|
29
49
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -55,17 +55,16 @@ module ElasticGraph
|
|
55
55
|
end
|
56
56
|
|
57
57
|
private_class_method def self.extract_buckets_from(search_response, for_query:)
|
58
|
-
search_response.
|
59
|
-
"aggregations",
|
58
|
+
search_response.aggregations.dig(
|
60
59
|
for_query.name,
|
61
60
|
"buckets"
|
62
|
-
) || [build_bucket(for_query, search_response
|
61
|
+
) || [build_bucket(for_query, search_response)]
|
63
62
|
end
|
64
63
|
|
65
64
|
private_class_method def self.build_bucket(query, response)
|
66
65
|
defaults = {
|
67
66
|
"key" => query.groupings.to_h { |g| [g.key, nil] },
|
68
|
-
"doc_count" => response.
|
67
|
+
"doc_count" => response.total_document_count(default: 0)
|
69
68
|
}
|
70
69
|
|
71
70
|
empty_bucket_computations = query.computations.to_h do |computation|
|
@@ -74,7 +73,7 @@ module ElasticGraph
|
|
74
73
|
|
75
74
|
defaults
|
76
75
|
.merge(empty_bucket_computations)
|
77
|
-
.merge(response
|
76
|
+
.merge(response.aggregations)
|
78
77
|
end
|
79
78
|
end
|
80
79
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -20,10 +20,6 @@ module ElasticGraph
|
|
20
20
|
module Aggregation
|
21
21
|
module Resolvers
|
22
22
|
class SubAggregations < ::Data.define(:schema_element_names, :sub_aggregations, :parent_queries, :sub_aggs_by_agg_key, :field_path)
|
23
|
-
def can_resolve?(field:, object:)
|
24
|
-
true
|
25
|
-
end
|
26
|
-
|
27
23
|
def resolve(field:, object:, args:, context:, lookahead:)
|
28
24
|
path_segment = PathSegment.for(field: field, lookahead: lookahead)
|
29
25
|
new_field_path = field_path + [path_segment]
|
@@ -69,15 +65,21 @@ module ElasticGraph
|
|
69
65
|
sub_agg
|
70
66
|
end
|
71
67
|
|
72
|
-
|
73
|
-
# Our resolver logic expects it to be present, though.
|
74
|
-
[singleton_bucket.merge({"doc_count_error_upper_bound" => 0})]
|
68
|
+
[SINGLETON_BUCKET_DEFAULTS.merge(singleton_bucket)]
|
75
69
|
end
|
76
70
|
end
|
77
71
|
|
78
72
|
BUCKET_ADAPTERS = [CompositeGroupingAdapter, NonCompositeGroupingAdapter].to_h do |adapter|
|
79
73
|
[adapter.meta_name, adapter]
|
80
74
|
end
|
75
|
+
|
76
|
+
SINGLETON_BUCKET_DEFAULTS = {
|
77
|
+
# When we have a single ungrouped bucket, we never have any error on the `doc_count`.
|
78
|
+
# Our resolver logic expects it to be present, though.
|
79
|
+
"doc_count_error_upper_bound" => 0,
|
80
|
+
# Our resolver logic expects a `key` as it gets used by the `PageInfo` resolver when that's requested.
|
81
|
+
"key" => {}
|
82
|
+
}
|
81
83
|
end
|
82
84
|
end
|
83
85
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -33,7 +33,7 @@ module ElasticGraph
|
|
33
33
|
clause_value = work_around_elasticsearch_bug(terms_subclause)
|
34
34
|
{
|
35
35
|
"terms" => clause_value.merge({
|
36
|
-
"size" => query.paginator.
|
36
|
+
"size" => query.paginator.requested_page_size,
|
37
37
|
"show_term_doc_count_error" => query.needs_doc_count_error
|
38
38
|
})
|
39
39
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -20,6 +20,12 @@ module ElasticGraph
|
|
20
20
|
:max_page_size,
|
21
21
|
# Queries that take longer than this configured threshold will have a sanitized version logged.
|
22
22
|
:slow_query_latency_warning_threshold_in_ms,
|
23
|
+
# How to resolve nested relationships:
|
24
|
+
#
|
25
|
+
# - `optimized` (default): uses the new (in ElasticGraph 0.19.2.0) optimized resolver logic.
|
26
|
+
# - `original`: uses the resolver logic from ElasticGraph v0.19.1.1 and before.
|
27
|
+
# - `comparison`: runs both versions of the logic in serial, to compare them for correctness and performance. Results are logged.
|
28
|
+
:nested_relationship_resolver_mode,
|
23
29
|
# Object used to identify the client of a GraphQL query based on the HTTP request.
|
24
30
|
:client_resolver,
|
25
31
|
# Array of modules that will be extended onto the `GraphQL` instance to support extension libraries.
|
@@ -38,17 +44,24 @@ module ElasticGraph
|
|
38
44
|
|
39
45
|
extension_loader = SchemaArtifacts::RuntimeMetadata::ExtensionLoader.new(::Module.new)
|
40
46
|
extension_mods = parsed_yaml.fetch("extension_modules", []).map do |mod_hash|
|
41
|
-
extension_loader.load(mod_hash.fetch("
|
47
|
+
extension_loader.load(mod_hash.fetch("name"), from: mod_hash.fetch("require_path"), config: {}).extension_class.tap do |mod|
|
42
48
|
unless mod.instance_of?(::Module)
|
43
|
-
raise Errors::ConfigError, "`#{mod_hash.fetch("
|
49
|
+
raise Errors::ConfigError, "`#{mod_hash.fetch("name")}` is not a module, but all application extension modules must be modules."
|
44
50
|
end
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
54
|
+
nested_relationship_resolver_mode = parsed_yaml["nested_relationship_resolver_mode"]&.to_sym || :optimized
|
55
|
+
unless VALID_NESTED_RELATIONSHIP_RESOLVER_MODES.include?(nested_relationship_resolver_mode)
|
56
|
+
raise Errors::ConfigError, "Invalid value for `nested_relationship_resolver_mode`: #{nested_relationship_resolver_mode}. " \
|
57
|
+
"Valid values: #{VALID_NESTED_RELATIONSHIP_RESOLVER_MODES.join(", ")}."
|
58
|
+
end
|
59
|
+
|
48
60
|
new(
|
49
61
|
default_page_size: parsed_yaml.fetch("default_page_size"),
|
50
62
|
max_page_size: parsed_yaml.fetch("max_page_size"),
|
51
63
|
slow_query_latency_warning_threshold_in_ms: parsed_yaml["slow_query_latency_warning_threshold_in_ms"] || 5000,
|
64
|
+
nested_relationship_resolver_mode: nested_relationship_resolver_mode,
|
52
65
|
client_resolver: load_client_resolver(parsed_yaml),
|
53
66
|
extension_modules: extension_mods,
|
54
67
|
extension_settings: entire_parsed_yaml.except(*ELASTICGRAPH_CONFIG_KEYS)
|
@@ -61,6 +74,8 @@ module ElasticGraph
|
|
61
74
|
# The standard ElasticGraph root config setting keys; anything else is assumed to be extension settings.
|
62
75
|
ELASTICGRAPH_CONFIG_KEYS = %w[graphql indexer logger datastore schema_artifacts]
|
63
76
|
|
77
|
+
VALID_NESTED_RELATIONSHIP_RESOLVER_MODES = [:optimized, :original, :comparison]
|
78
|
+
|
64
79
|
private_class_method def self.load_client_resolver(parsed_yaml)
|
65
80
|
config = parsed_yaml.fetch("client_resolver") do
|
66
81
|
return Client::DefaultResolver.new({})
|
@@ -68,13 +83,13 @@ module ElasticGraph
|
|
68
83
|
|
69
84
|
client_resolver_loader = SchemaArtifacts::RuntimeMetadata::ExtensionLoader.new(Client::DefaultResolver)
|
70
85
|
extension = client_resolver_loader.load(
|
71
|
-
config.fetch("
|
86
|
+
config.fetch("name"),
|
72
87
|
from: config.fetch("require_path"),
|
73
|
-
config: config.except("
|
88
|
+
config: config.except("name", "require_path")
|
74
89
|
)
|
75
90
|
extension_class = extension.extension_class # : ::Class
|
76
91
|
|
77
|
-
__skip__ = extension_class.new(extension.
|
92
|
+
__skip__ = extension_class.new(extension.config)
|
78
93
|
end
|
79
94
|
end
|
80
95
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -22,7 +22,9 @@ module ElasticGraph
|
|
22
22
|
:individual_docs_needed,
|
23
23
|
# `total_document_count_needed`: when false, `track_total_hits` will be 0 in our datastore query.
|
24
24
|
# This will prevent the datastore from doing extra work to get an accurate count
|
25
|
-
:total_document_count_needed
|
25
|
+
:total_document_count_needed,
|
26
|
+
:size_multiplier,
|
27
|
+
:max_effective_size
|
26
28
|
)
|
27
29
|
# Builds a hash containing the portions of a datastore search body related to pagination.
|
28
30
|
def to_datastore_body
|
@@ -57,12 +59,15 @@ module ElasticGraph
|
|
57
59
|
end
|
58
60
|
end
|
59
61
|
|
60
|
-
private
|
61
|
-
|
62
62
|
def effective_size
|
63
|
-
|
63
|
+
@effective_size ||= begin
|
64
|
+
uncapped_size = (individual_docs_needed ? paginator.requested_page_size : 0) * size_multiplier
|
65
|
+
(uncapped_size > max_effective_size) ? max_effective_size : uncapped_size
|
66
|
+
end
|
64
67
|
end
|
65
68
|
|
69
|
+
private
|
70
|
+
|
66
71
|
def effective_sort
|
67
72
|
return [] unless effective_size > 0
|
68
73
|
paginator.search_in_reverse? ? reverse_sort : sort
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -142,8 +142,7 @@ module ElasticGraph
|
|
142
142
|
private_constant :IndexExpressionBuilder
|
143
143
|
|
144
144
|
# Steep is complaining that it can't find some `Query` but they are not in this file...
|
145
|
-
# @dynamic
|
146
|
-
# @dynamic with, to_datastore_msearch_header_and_body, document_paginator
|
145
|
+
# @dynamic shard_routing_values, effective_size, merge_with, search_index_expression, with, to_datastore_msearch_header_and_body
|
147
146
|
end
|
148
147
|
end
|
149
148
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -168,8 +168,7 @@ module ElasticGraph
|
|
168
168
|
private_constant :RoutingValueSet
|
169
169
|
|
170
170
|
# Steep is complaining that it can't find some `Query` but they are not in this file...
|
171
|
-
# @dynamic
|
172
|
-
# @dynamic with, to_datastore_msearch_header_and_body, document_paginator
|
171
|
+
# @dynamic shard_routing_values, effective_size, merge_with, search_index_expression, with, to_datastore_msearch_header_and_body
|
173
172
|
end
|
174
173
|
end
|
175
174
|
end
|