elasticgraph-schema_definition 0.19.2.2 → 0.19.3.1
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/schema_definition/api.rb +12 -5
- data/lib/elastic_graph/schema_definition/factory.rb +4 -4
- data/lib/elastic_graph/schema_definition/indexing/derived_fields/append_only_set.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/derived_fields/field_initializer_support.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/derived_fields/immutable_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/derived_fields/min_or_max_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/derived_indexed_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/event_envelope.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_reference.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_type/enum.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_type/object.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_type/scalar.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_type/union.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/index.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/json_schema_field_metadata.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/json_schema_with_metadata.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/list_counts_mapping.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/relationship_resolver.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/rollover_config.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/update_target_factory.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/update_target_resolver.rb +1 -1
- data/lib/elastic_graph/schema_definition/json_schema_pruner.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/can_be_graphql_only.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_derived_graphql_type_customizations.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_directives.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_documentation.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_indices.rb +17 -4
- data/lib/elastic_graph/schema_definition/mixins/has_readable_to_s_and_inspect.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_subtypes.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_type_info.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/implements_interfaces.rb +13 -2
- data/lib/elastic_graph/schema_definition/mixins/supports_default_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/supports_filtering_and_aggregation.rb +7 -7
- data/lib/elastic_graph/schema_definition/mixins/verifies_graphql_name.rb +1 -1
- data/lib/elastic_graph/schema_definition/rake_tasks.rb +1 -1
- data/lib/elastic_graph/schema_definition/results.rb +5 -5
- data/lib/elastic_graph/schema_definition/schema_artifact_manager.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/argument.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/built_in_types.rb +113 -5
- data/lib/elastic_graph/schema_definition/schema_elements/deprecated_element.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/directive.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/enum_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/enum_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/enum_value_namer.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/enums_for_indexed_types.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/field.rb +94 -13
- data/lib/elastic_graph/schema_definition/schema_elements/field_path.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/field_source.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/graphql_sdl_enumerator.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/input_field.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/input_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/interface_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/list_counts_state.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/object_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/relationship.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/scalar_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/sort_order_enum_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/sub_aggregation_path.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/type_namer.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/type_reference.rb +10 -7
- data/lib/elastic_graph/schema_definition/schema_elements/type_with_subfields.rb +26 -7
- data/lib/elastic_graph/schema_definition/schema_elements/union_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/scripting/file_system_repository.rb +1 -1
- data/lib/elastic_graph/schema_definition/scripting/script.rb +1 -1
- data/lib/elastic_graph/schema_definition/state.rb +1 -1
- data/lib/elastic_graph/schema_definition/test_support.rb +1 -1
- metadata +26 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2024 -
|
|
1
|
+
# Copyright 2024 - 2026 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
|
|
@@ -152,6 +152,15 @@ module ElasticGraph
|
|
|
152
152
|
# GeoLocation
|
|
153
153
|
# : Geographic coordinates representing a location on the Earth's surface.
|
|
154
154
|
#
|
|
155
|
+
# GeoTile
|
|
156
|
+
# : A tile in the Web Mercator XYZ grid. Its coordinates identify a cell, not a fixed ground distance.
|
|
157
|
+
#
|
|
158
|
+
# GeoTileBounds
|
|
159
|
+
# : The geographic bounds of a Web Mercator XYZ tile. Tiles do not cross the antimeridian.
|
|
160
|
+
#
|
|
161
|
+
# GeoTileCorners
|
|
162
|
+
# : The geographic locations of the four corners of a Web Mercator XYZ tile.
|
|
163
|
+
#
|
|
155
164
|
# PageInfo
|
|
156
165
|
# : Provides information about the specific fetched page. This implements the
|
|
157
166
|
# `PageInfo` specification from the [Relay GraphQL Cursor Connections
|
|
@@ -180,6 +189,7 @@ module ElasticGraph
|
|
|
180
189
|
register_custom_elastic_graph_scalars
|
|
181
190
|
register_enum_types
|
|
182
191
|
register_date_and_time_grouped_by_types
|
|
192
|
+
register_geo_grouped_by_types
|
|
183
193
|
register_standard_elastic_graph_types
|
|
184
194
|
register_standard_graphql_resolvers
|
|
185
195
|
end
|
|
@@ -394,7 +404,7 @@ module ElasticGraph
|
|
|
394
404
|
# to go from non-null to null, but is not a breaking change to make it non-null
|
|
395
405
|
# in the future.
|
|
396
406
|
register_framework_object_type "PageInfo" do |t|
|
|
397
|
-
t.
|
|
407
|
+
t.resolve_fields_with :object_without_lookahead
|
|
398
408
|
|
|
399
409
|
t.documentation <<~EOS
|
|
400
410
|
Provides information about the specific fetched page. This implements the `PageInfo`
|
|
@@ -512,7 +522,7 @@ module ElasticGraph
|
|
|
512
522
|
|
|
513
523
|
register_framework_object_type "AggregationCountDetail" do |t|
|
|
514
524
|
t.documentation "Provides detail about an aggregation `#{names.count}`."
|
|
515
|
-
t.
|
|
525
|
+
t.resolve_fields_with :object_without_lookahead
|
|
516
526
|
|
|
517
527
|
t.field names.approximate_value, "JsonSafeLong!", graphql_only: true do |f|
|
|
518
528
|
f.documentation <<~EOS
|
|
@@ -1294,7 +1304,7 @@ module ElasticGraph
|
|
|
1294
1304
|
date = schema_def_state.type_ref("Date")
|
|
1295
1305
|
register_framework_object_type date.as_grouped_by.name do |t|
|
|
1296
1306
|
t.documentation "Allows for grouping `Date` values based on the desired return type."
|
|
1297
|
-
t.
|
|
1307
|
+
t.resolve_fields_with :object_with_lookahead
|
|
1298
1308
|
t.override_runtime_metadata(elasticgraph_category: :date_grouped_by_object)
|
|
1299
1309
|
|
|
1300
1310
|
t.field names.as_date, "Date", graphql_only: true do |f|
|
|
@@ -1312,7 +1322,7 @@ module ElasticGraph
|
|
|
1312
1322
|
date_time = schema_def_state.type_ref("DateTime")
|
|
1313
1323
|
register_framework_object_type date_time.as_grouped_by.name do |t|
|
|
1314
1324
|
t.documentation "Allows for grouping `DateTime` values based on the desired return type."
|
|
1315
|
-
t.
|
|
1325
|
+
t.resolve_fields_with :object_with_lookahead
|
|
1316
1326
|
t.override_runtime_metadata(elasticgraph_category: :date_grouped_by_object)
|
|
1317
1327
|
|
|
1318
1328
|
t.field names.as_date_time, "DateTime", graphql_only: true do |f|
|
|
@@ -1369,7 +1379,105 @@ module ElasticGraph
|
|
|
1369
1379
|
end
|
|
1370
1380
|
end
|
|
1371
1381
|
|
|
1382
|
+
# Registers the geographic grouping operation and its tile, bounds, and corner output types.
|
|
1383
|
+
def register_geo_grouped_by_types
|
|
1384
|
+
register_framework_object_type schema_def_state.type_ref("GeoLocation").as_grouped_by.name do |t|
|
|
1385
|
+
t.documentation "Offers geographic grouping representations for a location."
|
|
1386
|
+
t.resolve_fields_with :object_with_lookahead
|
|
1387
|
+
t.override_runtime_metadata(elasticgraph_category: :geo_location_grouped_by_object)
|
|
1388
|
+
|
|
1389
|
+
t.field names.as_geo_tile, "GeoTile", graphql_only: true do |f|
|
|
1390
|
+
f.resolve_with :as_geo_tile
|
|
1391
|
+
|
|
1392
|
+
f.documentation <<~EOS
|
|
1393
|
+
Groups locations into Web Mercator [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames). Missing locations produce a `null` tile.
|
|
1394
|
+
Points beyond ±85.0511° latitude are grouped into the northernmost or southernmost row,
|
|
1395
|
+
so a point can be outside the bounds of the tile it is grouped into.
|
|
1396
|
+
Boundary points are assigned to the tile to the east or south, subject to datastore coordinate encoding.
|
|
1397
|
+
EOS
|
|
1398
|
+
|
|
1399
|
+
f.argument names.zoom_level, "Int!" do |a|
|
|
1400
|
+
a.documentation <<~EOS
|
|
1401
|
+
The Web Mercator zoom level, from #{GEO_TILE_ZOOM_LEVELS.min} through #{GEO_TILE_ZOOM_LEVELS.max}.
|
|
1402
|
+
At zoom level z, the map has 2^z rows and 2^z columns. Increasing the zoom level by 1
|
|
1403
|
+
doubles both, producing four times as many tiles.
|
|
1404
|
+
EOS
|
|
1405
|
+
a.default 7
|
|
1406
|
+
end
|
|
1407
|
+
end
|
|
1408
|
+
end
|
|
1409
|
+
|
|
1410
|
+
register_framework_object_type "GeoTile" do |t|
|
|
1411
|
+
t.documentation "A tile in the Web Mercator XYZ grid. Its coordinates identify a cell, not a fixed ground distance."
|
|
1412
|
+
t.resolve_fields_with :object_without_lookahead
|
|
1413
|
+
|
|
1414
|
+
t.field names.zoom_level, "Int!", graphql_only: true do |f|
|
|
1415
|
+
f.documentation "The zoom level of the tile, from #{GEO_TILE_ZOOM_LEVELS.min} through #{GEO_TILE_ZOOM_LEVELS.max}."
|
|
1416
|
+
end
|
|
1417
|
+
|
|
1418
|
+
{names.x => "west to east", names.y => "north to south"}.each do |name, direction|
|
|
1419
|
+
t.field name, "Int!", graphql_only: true do |f|
|
|
1420
|
+
f.documentation "The zero-based tile coordinate, counted #{direction}, from 0 through 2^zoomLevel - 1."
|
|
1421
|
+
end
|
|
1422
|
+
end
|
|
1423
|
+
|
|
1424
|
+
t.field names.map_center_point, "GeoLocation!", graphql_only: true do |f|
|
|
1425
|
+
f.documentation <<~EOS
|
|
1426
|
+
The center of the tile as drawn on a Web Mercator map, not the average record location or the midpoint
|
|
1427
|
+
of the tile's latitude bounds. These differ noticeably only at low zoom levels: for tile 1/0/0,
|
|
1428
|
+
the map center point is at about 66.51° latitude, but the bounds midpoint is at about 42.53°.
|
|
1429
|
+
EOS
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
t.field names.bounds, "GeoTileBounds!", graphql_only: true do |f|
|
|
1433
|
+
f.documentation "The geographic bounds of the tile. Web Mercator excludes the poles and stops at approximately ±85.0511°."
|
|
1434
|
+
end
|
|
1435
|
+
|
|
1436
|
+
t.field names.corners, "GeoTileCorners!", graphql_only: true do |f|
|
|
1437
|
+
f.documentation "The four corners of the tile, calculated from its geographic bounds."
|
|
1438
|
+
end
|
|
1439
|
+
end
|
|
1440
|
+
|
|
1441
|
+
register_framework_object_type "GeoTileBounds" do |t|
|
|
1442
|
+
t.resolve_fields_with :object_without_lookahead
|
|
1443
|
+
t.documentation "The geographic bounds of a Web Mercator XYZ tile. Tiles do not cross the antimeridian."
|
|
1444
|
+
|
|
1445
|
+
{
|
|
1446
|
+
names.north => "latitude of the northern",
|
|
1447
|
+
names.south => "latitude of the southern",
|
|
1448
|
+
names.east => "longitude of the eastern",
|
|
1449
|
+
names.west => "longitude of the western"
|
|
1450
|
+
}.each do |name, description|
|
|
1451
|
+
t.field name, "Float!", graphql_only: true do |f|
|
|
1452
|
+
f.documentation "The #{description} boundary of the tile."
|
|
1453
|
+
end
|
|
1454
|
+
end
|
|
1455
|
+
end
|
|
1456
|
+
|
|
1457
|
+
register_framework_object_type "GeoTileCorners" do |t|
|
|
1458
|
+
t.resolve_fields_with :object_without_lookahead
|
|
1459
|
+
t.documentation "The geographic locations of the four corners of a Web Mercator XYZ tile."
|
|
1460
|
+
|
|
1461
|
+
{
|
|
1462
|
+
names.northwest => "northwest",
|
|
1463
|
+
names.northeast => "northeast",
|
|
1464
|
+
names.southwest => "southwest",
|
|
1465
|
+
names.southeast => "southeast"
|
|
1466
|
+
}.each do |name, description|
|
|
1467
|
+
t.field name, "GeoLocation!", graphql_only: true do |f|
|
|
1468
|
+
f.documentation "The #{description} corner of the tile."
|
|
1469
|
+
end
|
|
1470
|
+
end
|
|
1471
|
+
end
|
|
1472
|
+
end
|
|
1473
|
+
|
|
1372
1474
|
def register_standard_graphql_resolvers
|
|
1475
|
+
require(require_path = "elastic_graph/graphql/aggregation/resolvers/as_geo_tile")
|
|
1476
|
+
schema_def_api.register_graphql_resolver :as_geo_tile,
|
|
1477
|
+
GraphQL::Aggregation::Resolvers::AsGeoTile,
|
|
1478
|
+
defined_at: require_path,
|
|
1479
|
+
built_in: true
|
|
1480
|
+
|
|
1373
1481
|
require(require_path = "elastic_graph/graphql/resolvers/get_record_field_value")
|
|
1374
1482
|
schema_def_api.register_graphql_resolver :get_record_field_value,
|
|
1375
1483
|
GraphQL::Resolvers::GetRecordFieldValue,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2024 -
|
|
1
|
+
# Copyright 2024 - 2026 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
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
require "delegate"
|
|
10
10
|
require "elastic_graph/constants"
|
|
11
|
+
require "elastic_graph/schema_artifacts/runtime_metadata/configured_graphql_resolver"
|
|
11
12
|
require "elastic_graph/schema_definition/indexing/field"
|
|
12
13
|
require "elastic_graph/schema_definition/indexing/field_reference"
|
|
13
14
|
require "elastic_graph/schema_definition/mixins/has_directives"
|
|
@@ -80,8 +81,6 @@ module ElasticGraph
|
|
|
80
81
|
# @private
|
|
81
82
|
# @!attribute [rw] non_nullable_in_json_schema
|
|
82
83
|
# @private
|
|
83
|
-
# @!attribute [rw] backing_indexing_field
|
|
84
|
-
# @private
|
|
85
84
|
# @!attribute [rw] as_input
|
|
86
85
|
# @private
|
|
87
86
|
# @!attribute [rw] legacy_grouping_schema
|
|
@@ -91,7 +90,7 @@ module ElasticGraph
|
|
|
91
90
|
:filter_customizations, :grouped_by_customizations, :sub_aggregations_customizations,
|
|
92
91
|
:aggregated_values_customizations, :sort_order_enum_value_customizations,
|
|
93
92
|
:args, :sortable, :filterable, :aggregatable, :groupable, :graphql_only, :source, :runtime_field_script, :relationship, :singular_name,
|
|
94
|
-
:computation_detail, :non_nullable_in_json_schema, :
|
|
93
|
+
:computation_detail, :non_nullable_in_json_schema, :as_input,
|
|
95
94
|
:legacy_grouping_schema, :name_in_index, :resolver
|
|
96
95
|
)
|
|
97
96
|
include Mixins::HasDocumentation
|
|
@@ -105,7 +104,7 @@ module ElasticGraph
|
|
|
105
104
|
accuracy_confidence: :high, name_in_index: name,
|
|
106
105
|
type_for_derived_types: nil, graphql_only: nil, singular: nil,
|
|
107
106
|
sortable: nil, filterable: nil, aggregatable: nil, groupable: nil,
|
|
108
|
-
|
|
107
|
+
as_input: false, legacy_grouping_schema: false, resolver: nil
|
|
109
108
|
)
|
|
110
109
|
type_ref = schema_def_state.type_ref(type)
|
|
111
110
|
super(
|
|
@@ -134,20 +133,33 @@ module ElasticGraph
|
|
|
134
133
|
singular_name: singular,
|
|
135
134
|
name_in_index: name_in_index,
|
|
136
135
|
non_nullable_in_json_schema: false,
|
|
137
|
-
backing_indexing_field: backing_indexing_field,
|
|
138
136
|
as_input: as_input,
|
|
139
137
|
legacy_grouping_schema: legacy_grouping_schema,
|
|
140
138
|
resolver: resolver
|
|
141
139
|
)
|
|
142
140
|
|
|
143
|
-
if name != name_in_index
|
|
144
|
-
|
|
141
|
+
if name != name_in_index
|
|
142
|
+
if graphql_only
|
|
143
|
+
schema_def_state.after_user_definition_complete do
|
|
144
|
+
unless backing_indexing_field
|
|
145
|
+
raise Errors::SchemaError,
|
|
146
|
+
"GraphQL-only field `#{parent_type.name}.#{name}` has a `name_in_index` (#{name_in_index}) which does not reference an " \
|
|
147
|
+
"existing indexing field. To proceed, remove `graphql_only: true` or update `name_in_index` to match an existing indexing field."
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
elsif name_in_index.include?(".")
|
|
151
|
+
raise Errors::SchemaError,
|
|
152
|
+
"#{self} has an invalid `name_in_index`: #{name_in_index.inspect}. " \
|
|
153
|
+
"Only `graphql_only: true` fields can have a `name_in_index` that references a child field."
|
|
154
|
+
end
|
|
145
155
|
end
|
|
146
156
|
|
|
147
157
|
schema_def_state.register_user_defined_field(self)
|
|
148
158
|
yield self if block_given?
|
|
149
159
|
end
|
|
150
160
|
|
|
161
|
+
private :resolver=
|
|
162
|
+
|
|
151
163
|
# @private
|
|
152
164
|
@@initialize_param_names = instance_method(:initialize).parameters.map(&:last).to_set
|
|
153
165
|
|
|
@@ -448,6 +460,46 @@ module ElasticGraph
|
|
|
448
460
|
)
|
|
449
461
|
end
|
|
450
462
|
|
|
463
|
+
# Configures the GraphQL resolver used to resolve this field. If not set, the resolver configured on the parent type
|
|
464
|
+
# via {Mixins::HasIndices#resolve_fields_with} will be used.
|
|
465
|
+
#
|
|
466
|
+
# @param resolver_name [Symbol] name of the GraphQL resolver
|
|
467
|
+
# @param config [Hash<Symbol, Object>] configuration parameters for the resolver
|
|
468
|
+
# @return [void]
|
|
469
|
+
# @see API#register_graphql_resolver
|
|
470
|
+
#
|
|
471
|
+
# @example Use a custom resolver for a custom `Query` field
|
|
472
|
+
# # In `add_resolver.rb`:
|
|
473
|
+
# class AddResolver
|
|
474
|
+
# def initialize(elasticgraph_graphql:, config:)
|
|
475
|
+
# @multiplier = config.fetch(:multiplier, 1)
|
|
476
|
+
# end
|
|
477
|
+
#
|
|
478
|
+
# def resolve(field:, object:, args:, context:)
|
|
479
|
+
# sum = args.fetch("x") + args.fetch("y")
|
|
480
|
+
# sum * @multiplier
|
|
481
|
+
# end
|
|
482
|
+
# end
|
|
483
|
+
#
|
|
484
|
+
# # In `config/schema.rb`:
|
|
485
|
+
# ElasticGraph.define_schema do |schema|
|
|
486
|
+
# require(resolver_path = "add_resolver")
|
|
487
|
+
# schema.register_graphql_resolver :add, AddResolver, defined_at: resolver_path
|
|
488
|
+
#
|
|
489
|
+
# schema.on_root_query_type do |t|
|
|
490
|
+
# t.field "add", "Int" do |f|
|
|
491
|
+
# f.argument "x", "Int!"
|
|
492
|
+
# f.argument "y", "Int!"
|
|
493
|
+
#
|
|
494
|
+
# # Extra args (`multiplier: 2`, in this example) are passed to the resolver within `config`.
|
|
495
|
+
# f.resolve_with :add, multiplier: 2
|
|
496
|
+
# end
|
|
497
|
+
# end
|
|
498
|
+
# end
|
|
499
|
+
def resolve_with(resolver_name, **config)
|
|
500
|
+
self.resolver = resolver_name&.then { |name| SchemaArtifacts::RuntimeMetadata::ConfiguredGraphQLResolver.new(name, config) }
|
|
501
|
+
end
|
|
502
|
+
|
|
451
503
|
# @private
|
|
452
504
|
def runtime_script(script)
|
|
453
505
|
self.runtime_field_script = script
|
|
@@ -557,13 +609,14 @@ module ElasticGraph
|
|
|
557
609
|
# instead.
|
|
558
610
|
return false if parent_type.indexed? && name == "id"
|
|
559
611
|
|
|
560
|
-
return false if relationship ||
|
|
612
|
+
return false if relationship || type_disallows_grouping?
|
|
561
613
|
|
|
562
614
|
# We don't support grouping an entire list of values, but we do support grouping on individual values in a list.
|
|
563
615
|
# However, we only do so when a `singular_name` has been provided (so that we know what to call the grouped_by field).
|
|
564
616
|
# The semantics are a little odd (since one document can be duplicated in multiple grouping buckets) so we're ok
|
|
565
617
|
# with not offering it by default--the user has to opt-in by telling us what to call the field in its singular form.
|
|
566
|
-
|
|
618
|
+
# Types with their own `GroupedBy` type are grouped as individual values, like scalars.
|
|
619
|
+
return list_field_groupable_by_single_values? if type.list? && (type.fully_unwrapped.leaf? || original_type.fully_unwrapped.grouped_by_type_defined?)
|
|
567
620
|
|
|
568
621
|
# Nested fields will be supported through specific nested aggregation support, and do not
|
|
569
622
|
# work as expected when grouping on the root document type.
|
|
@@ -678,11 +731,13 @@ module ElasticGraph
|
|
|
678
731
|
end
|
|
679
732
|
end
|
|
680
733
|
|
|
734
|
+
# Returns the GraphQL type used for this field's grouped value.
|
|
681
735
|
# @private
|
|
682
736
|
def grouped_by_field_type_name
|
|
683
737
|
unwrapped_type = type_for_derived_types.fully_unwrapped
|
|
684
|
-
|
|
685
|
-
|
|
738
|
+
original_unwrapped_type = original_type_for_derived_types.fully_unwrapped
|
|
739
|
+
if original_unwrapped_type.grouped_by_type_defined? && !legacy_grouping_schema
|
|
740
|
+
original_unwrapped_type.as_grouped_by.name
|
|
686
741
|
elsif unwrapped_type.leaf?
|
|
687
742
|
unwrapped_type.name
|
|
688
743
|
else
|
|
@@ -702,7 +757,7 @@ module ElasticGraph
|
|
|
702
757
|
"The `#{name}` field value for this group",
|
|
703
758
|
list_field_grouped_by_doc_note("the selected subfields of `#{name}`")
|
|
704
759
|
)
|
|
705
|
-
elsif
|
|
760
|
+
elsif original_type_for_derived_types.fully_unwrapped.grouped_by_type_defined? && !legacy_grouping_schema
|
|
706
761
|
derived_documentation("Offers the different grouping options for the `#{name}` value within this group")
|
|
707
762
|
else
|
|
708
763
|
derived_documentation("The `#{name}` field value for this group")
|
|
@@ -934,6 +989,27 @@ module ElasticGraph
|
|
|
934
989
|
)
|
|
935
990
|
end
|
|
936
991
|
|
|
992
|
+
# The alternate field that is backing this field in the datastore index. Will only be non-`nil` for `graphql_only` fields.
|
|
993
|
+
# @return [Field, nil] the field backing this field in the index
|
|
994
|
+
#
|
|
995
|
+
# @private
|
|
996
|
+
def backing_indexing_field
|
|
997
|
+
return nil unless graphql_only
|
|
998
|
+
|
|
999
|
+
type = parent_type
|
|
1000
|
+
field = nil
|
|
1001
|
+
|
|
1002
|
+
name_in_index.split(".").each do |path_part|
|
|
1003
|
+
if (field = type&.indexing_fields_by_name_in_index&.fetch(path_part, nil))
|
|
1004
|
+
type = field.type.fully_unwrapped.as_object_type
|
|
1005
|
+
else
|
|
1006
|
+
return nil
|
|
1007
|
+
end
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
field
|
|
1011
|
+
end
|
|
1012
|
+
|
|
937
1013
|
private
|
|
938
1014
|
|
|
939
1015
|
def args_sdl(joiner:, after_opening_paren: "", &arg_selector)
|
|
@@ -943,6 +1019,11 @@ module ElasticGraph
|
|
|
943
1019
|
"(#{after_opening_paren}#{args_sdl})"
|
|
944
1020
|
end
|
|
945
1021
|
|
|
1022
|
+
# Identifies types that disallow grouping, except for types that define their own `GroupedBy` type.
|
|
1023
|
+
def type_disallows_grouping?
|
|
1024
|
+
!original_type.fully_unwrapped.grouped_by_type_defined? && !!type.fully_unwrapped.as_object_type&.does_not_support?(&:groupable?)
|
|
1025
|
+
end
|
|
1026
|
+
|
|
946
1027
|
# Indicates if the field uses the `text` mapping type.
|
|
947
1028
|
def text?
|
|
948
1029
|
mapping_type == "text"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2024 -
|
|
1
|
+
# Copyright 2024 - 2026 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
|
|
@@ -153,12 +153,15 @@ module ElasticGraph
|
|
|
153
153
|
.sub(/[\]!]+\z/, "") # strip `]` and `!` characters from the end: https://rubular.com/r/pC8C0i7EpvHDbf
|
|
154
154
|
end
|
|
155
155
|
|
|
156
|
-
#
|
|
157
|
-
#
|
|
158
|
-
#
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
156
|
+
# Indicates if this type opts into specialized grouping by defining its own `[type]GroupedBy` type.
|
|
157
|
+
# Use the original type name, before overrides, since an overridden name may identify another type.
|
|
158
|
+
# Only call this after the user definition is complete, when all grouping types are known.
|
|
159
|
+
def grouped_by_type_defined?
|
|
160
|
+
unless schema_def_state.user_definition_complete
|
|
161
|
+
raise Errors::SchemaError, "Cannot call `grouped_by_type_defined?` until the schema definition is complete."
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
schema_def_state.types_by_name.key?(as_grouped_by.name)
|
|
162
165
|
end
|
|
163
166
|
|
|
164
167
|
# Returns a new `TypeReference` with any type name overrides reverted (to provide the "original" type name).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2024 -
|
|
1
|
+
# Copyright 2024 - 2026 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
|
|
@@ -279,6 +279,12 @@ module ElasticGraph
|
|
|
279
279
|
# differently named field in the index.
|
|
280
280
|
# @param singular [String] indicates what the singular form of a field's name is. When provided, ElasticGraph will define a
|
|
281
281
|
# `groupedBy` field (using the singular form) allowing clients to group by individual values from the field.
|
|
282
|
+
# @param aggregatable [Boolean] force-enables or disables the ability for aggregation queries to aggregate over this field.
|
|
283
|
+
# When not provided, ElasticGraph will infer field aggregatability based on the field's GraphQL type and mapping type.
|
|
284
|
+
# @param filterable [Boolean] force-enables or disables the ability for queries to filter by this field. When not provided,
|
|
285
|
+
# ElasticGraph will infer field filterability based on the field's GraphQL type and mapping type.
|
|
286
|
+
# @param groupable [Boolean] force-enables or disables the ability for aggregation queries to group by this field. When
|
|
287
|
+
# not provided, ElasticGraph will infer field groupability based on the field's GraphQL type and mapping type.
|
|
282
288
|
# @yield [Field] the field for further customization
|
|
283
289
|
# @return [void]
|
|
284
290
|
#
|
|
@@ -295,24 +301,37 @@ module ElasticGraph
|
|
|
295
301
|
# t.index "authors"
|
|
296
302
|
# end
|
|
297
303
|
# end
|
|
298
|
-
def paginated_collection_field(
|
|
304
|
+
def paginated_collection_field(
|
|
305
|
+
name,
|
|
306
|
+
element_type,
|
|
307
|
+
name_in_index: name,
|
|
308
|
+
graphql_only: false,
|
|
309
|
+
singular: nil,
|
|
310
|
+
groupable: !!singular,
|
|
311
|
+
filterable: nil,
|
|
312
|
+
aggregatable: nil,
|
|
313
|
+
&block
|
|
314
|
+
)
|
|
299
315
|
element_type_ref = schema_def_state.type_ref(element_type).to_final_form
|
|
300
316
|
element_type = element_type_ref.name
|
|
301
317
|
|
|
302
318
|
schema_def_state.paginated_collection_element_types << element_type
|
|
303
319
|
|
|
304
|
-
|
|
320
|
+
unless graphql_only
|
|
321
|
+
field(name, "[#{element_type}!]!", indexing_only: true, name_in_index: name_in_index, &block)
|
|
322
|
+
end
|
|
305
323
|
|
|
306
324
|
field(
|
|
307
325
|
name,
|
|
308
326
|
element_type_ref.as_connection.name,
|
|
309
327
|
name_in_index: name_in_index,
|
|
310
328
|
type_for_derived_types: "[#{element_type}]",
|
|
311
|
-
groupable: !!singular,
|
|
312
|
-
sortable: false,
|
|
313
329
|
graphql_only: true,
|
|
314
330
|
singular: singular,
|
|
315
|
-
|
|
331
|
+
groupable: groupable,
|
|
332
|
+
filterable: filterable,
|
|
333
|
+
aggregatable: aggregatable,
|
|
334
|
+
sortable: false
|
|
316
335
|
) do |f|
|
|
317
336
|
f.define_relay_pagination_arguments!
|
|
318
337
|
block&.call(f)
|
|
@@ -536,7 +555,7 @@ module ElasticGraph
|
|
|
536
555
|
)
|
|
537
556
|
|
|
538
557
|
field.relationship = relationship
|
|
539
|
-
field.
|
|
558
|
+
field.resolve_with :nested_relationships
|
|
540
559
|
|
|
541
560
|
yield relationship if block_given?
|
|
542
561
|
|