elasticgraph-schema_definition 0.19.2.1 → 1.0.0.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa12b20af98ac82e8d84681ad3cb5f342d496fff461dadb54252dc44e5cb8202
4
- data.tar.gz: f8ad7f681ba53c230931ec5f7338dafd10a611d668f9069b37122c23cf529d22
3
+ metadata.gz: 54e9fd94b73a36f09e090c68605743766da45b9f1777e5622a8b1b0e6985a5a5
4
+ data.tar.gz: c656f8bf79e9dcfa7bf88d9f4e2944a606d436b440e337fd3db9d064ad59aad5
5
5
  SHA512:
6
- metadata.gz: fa2e0bd0e057cdc776384c0063426a5d85d0b36f1668edb0e15949699cbf7b67e1596f702361a20a5a5be54d20441ecd44d616110d2434db7a6b6ffb99a9e76b
7
- data.tar.gz: 7294c2075b4ef69c6f40bb53e2d478a67f196a9c5936e57cf90dbcaadeb8a951b8a9581b676d4686c70b96a391965172324d4f239f64ce0d7059bf54d075c867
6
+ metadata.gz: d348ef2187ff3dbd29c7c3c198a61153fdf86219bca6b37c35f92bafa0bbc17a26ac46d655f5a871c5d33f14568d27ff91a413ed1431a714491119b94d2ac67b
7
+ data.tar.gz: 7db25426957cd9ddfd2a0af5ee78c7248040a270438d95016b73edf9e2c74a08f830866f17a381488bf11706624ef0c58cfe41405b2eaaa485b5277fd2f75914
@@ -433,6 +433,8 @@ module ElasticGraph
433
433
 
434
434
  def edge_type_for(type_name)
435
435
  type_ref = @state.type_ref(type_name)
436
+ object_type = type_ref.as_object_type # : SchemaElements::ObjectType
437
+
436
438
  new_object_type type_ref.as_edge.name do |t|
437
439
  t.relay_pagination_type = true
438
440
  t.default_graphql_resolver = :object_without_lookahead
@@ -440,7 +442,7 @@ module ElasticGraph
440
442
 
441
443
  t.documentation <<~EOS
442
444
  Represents a specific `#{type_name}` in the context of a `#{type_ref.as_connection.name}`,
443
- providing access to both the `#{type_name}` and a pagination `Cursor`.
445
+ providing access to both the `#{type_name}` and query-specific information such as the pagination `Cursor`.
444
446
 
445
447
  See the [Relay GraphQL Cursor Connections
446
448
  Specification](https://relay.dev/graphql/connections.htm#sec-Edge-Types) for more info.
@@ -456,6 +458,18 @@ module ElasticGraph
456
458
  a `before` or `after` argument to continue paginating from this `#{type_name}`.
457
459
  EOS
458
460
  end
461
+
462
+ if object_type&.indexed?
463
+ t.field @state.schema_elements.all_highlights, "[SearchHighlight!]!" do |f|
464
+ f.documentation "All search highlights for this `#{type_name}`, indicating where in the indexed document the query matched."
465
+ end
466
+
467
+ if object_type.supports?(&:highlightable?)
468
+ t.field @state.schema_elements.highlights, type_ref.as_highlights.name do |f|
469
+ f.documentation "Specific search highlights for this `#{type_name}`, providing matching snippets for the requested fields."
470
+ end
471
+ end
472
+ end
459
473
  end
460
474
  end
461
475
 
@@ -42,7 +42,7 @@ module ElasticGraph
42
42
  :norms,
43
43
  :null_value,
44
44
  :search_analyzer,
45
- :type,
45
+ :type
46
46
  ]
47
47
 
48
48
  # Defines the Elasticsearch/OpenSearch [field mapping type](https://www.elastic.co/guide/en/elasticsearch/reference/7.10/mapping-types.html)
@@ -70,7 +70,8 @@ module ElasticGraph
70
70
  build_aggregation_sub_aggregations_types + [
71
71
  indexed_agg_type,
72
72
  to_grouped_by_type,
73
- to_aggregated_values_type
73
+ to_aggregated_values_type,
74
+ to_highlights_type
74
75
  ].compact
75
76
  end
76
77
 
@@ -263,6 +264,20 @@ module ElasticGraph
263
264
  end
264
265
  end
265
266
 
267
+ def to_highlights_type
268
+ # If the type uses a custom mapping type we don't know how it can be highlighted, so we assume it needs no highlights type.
269
+ return nil if does_not_support?(&:highlightable?)
270
+
271
+ new_non_empty_object_type type_ref.as_highlights.name do |t|
272
+ t.documentation "Type used to request desired `#{name}` search highlight fields."
273
+ t.default_graphql_resolver = :get_record_field_value
274
+
275
+ graphql_fields_by_name.values.each do |field|
276
+ field.define_highlights_field(t)
277
+ end
278
+ end
279
+ end
280
+
266
281
  def new_non_empty_object_type(name, &block)
267
282
  type = schema_def_state.factory.new_object_type(name, &block)
268
283
  type unless type.graphql_fields_by_name.empty?
@@ -109,15 +109,9 @@ module ElasticGraph
109
109
  # ElasticGraph defines these enum types. Most of these are intended for usage as an _input_
110
110
  # argument, but they could be used as a return type in your schema if they meet your needs.
111
111
  #
112
- # DateGroupingGranularity
113
- # : Enumerates the supported granularities of a `Date`.
114
- #
115
112
  # DateGroupingTruncationUnit
116
113
  # : Enumerates the supported truncation units of a `Date`.
117
114
  #
118
- # DateTimeGroupingGranularity
119
- # : Enumerates the supported granularities of a `DateTime`.
120
- #
121
115
  # DateTimeGroupingTruncationUnit
122
116
  # : Enumerates the supported truncation units of a `DateTime`.
123
117
  #
@@ -157,6 +151,9 @@ module ElasticGraph
157
151
  # `PageInfo` specification from the [Relay GraphQL Cursor Connections
158
152
  # Specification](https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo).
159
153
  #
154
+ # SearchHighlight
155
+ # : Provides information about why a document matched a search via highlighted snippets.
156
+ #
160
157
  # @!attribute [rw] schema_def_api
161
158
  # @private
162
159
  # @!attribute [rw] schema_def_state
@@ -206,23 +203,6 @@ module ElasticGraph
206
203
  def register_standard_elastic_graph_types
207
204
  # This is a special filter on a `String` type, so we don't have a `Text` scalar to generate it from.
208
205
  schema_def_state.factory.build_standard_filter_input_types_for_index_leaf_type("String", name_prefix: "Text") do |t|
209
- # We can't support filtering on `null` within a list, so make the field non-nullable when it's the
210
- # `ListElementFilterInput` type. See scalar_type.rb for a larger comment explaining the rationale behind this.
211
- equal_to_any_of_type = t.type_ref.list_element_filter_input? ? "[String!]" : "[String]"
212
- t.field names.equal_to_any_of, equal_to_any_of_type do |f|
213
- f.documentation ScalarType::EQUAL_TO_ANY_OF_DOC
214
- end
215
-
216
- t.field names.matches, "String" do |f|
217
- f.documentation <<~EOS
218
- Matches records where the field value matches the provided value using full text search.
219
-
220
- When `null` is passed, matches all documents.
221
- EOS
222
-
223
- f.directive "deprecated", reason: "Use `#{names.matches_query}` instead."
224
- end
225
-
226
206
  t.field names.matches_query, schema_def_state.type_ref("MatchesQuery").as_filter_input.name do |f|
227
207
  f.documentation <<~EOS
228
208
  Matches records where the field value matches the provided query using full text search.
@@ -300,7 +280,71 @@ module ElasticGraph
300
280
  f.documentation "The input phrase to search for."
301
281
  end
302
282
 
303
- # any_of/all_of/not don't really make sense on this filter because it doesn't make
283
+ # any_of/all_of/not don't really make sense on this filter because it doesn't make sense
284
+ # to apply an OR operator or negation to the fields of this type since they are all an
285
+ # indivisible part of a single filter operation on a specific field. So we remove them
286
+ # here.
287
+ remove_any_of_and_all_of_and_not_filter_operators_on(t)
288
+ end
289
+
290
+ register_filter "StringContains" do |t|
291
+ t.documentation <<~EOS
292
+ Input type used to specify parameters for the `#{names.contains}` string filtering operator.
293
+
294
+ When `null` is passed, matches all documents.
295
+ EOS
296
+
297
+ t.field names.any_substring_of, "[String!]" do |f|
298
+ f.documentation <<~EOS
299
+ Matches records where the field value contains one or more of the provided substrings.
300
+
301
+ When `null` is passed, matches all documents. When an empty list is passed,
302
+ this part of the filter matches no documents.
303
+ EOS
304
+ end
305
+
306
+ t.field names.all_substrings_of, "[String!]" do |f|
307
+ f.documentation <<~EOS
308
+ Matches records where the field value contains all of the provided substrings.
309
+
310
+ When `null` is passed or an empty list is passed, matches all documents.
311
+ EOS
312
+ end
313
+
314
+ t.field names.ignore_case, "Boolean!" do |f|
315
+ f.default false
316
+ f.documentation "Determines if the substring matching is case-sensitive (the default) or case-insensitive."
317
+ end
318
+
319
+ # any_of/all_of/not don't really make sense on this filter because it doesn't make sense
320
+ # to apply an OR operator or negation to the fields of this type since they are all an
321
+ # indivisible part of a single filter operation on a specific field. So we remove them
322
+ # here.
323
+ remove_any_of_and_all_of_and_not_filter_operators_on(t)
324
+ end
325
+
326
+ register_filter "StringStartsWith" do |t|
327
+ t.documentation <<~EOS
328
+ Input type used to specify parameters for the `#{names.starts_with}` string filtering operator.
329
+
330
+ When `null` is passed, matches all documents.
331
+ EOS
332
+
333
+ t.field names.any_prefix_of, "[String!]" do |f|
334
+ f.documentation <<~EOS
335
+ Matches records where the field value starts with one or more of the provided prefixes.
336
+
337
+ When `null` is passed, matches all documents. When an empty list is passed,
338
+ this part of the filter matches no documents.
339
+ EOS
340
+ end
341
+
342
+ t.field names.ignore_case, "Boolean!" do |f|
343
+ f.default false
344
+ f.documentation "Determines if the prefix matching is case-sensitive (the default) or case-insensitive."
345
+ end
346
+
347
+ # any_of/all_of/not don't really make sense on this filter because it doesn't make sense
304
348
  # to apply an OR operator or negation to the fields of this type since they are all an
305
349
  # indivisible part of a single filter operation on a specific field. So we remove them
306
350
  # here.
@@ -425,6 +469,23 @@ module ElasticGraph
425
469
  end
426
470
  end
427
471
 
472
+ register_framework_object_type "SearchHighlight" do |t|
473
+ t.default_graphql_resolver = :object_without_lookahead
474
+
475
+ t.documentation "Provides information about why a document matched a search via highlighted snippets."
476
+
477
+ t.field names.path, "[String!]!" do |f|
478
+ f.documentation <<~EOS
479
+ Path to a leaf field containing one or more search highlight snippets. The returned list will contain a path segment for
480
+ each object layer of the schema, from the document root.
481
+ EOS
482
+ end
483
+
484
+ t.field names.snippets, "[String!]!" do |f|
485
+ f.documentation "List of snippets containing search highlights from field values at this `path`."
486
+ end
487
+ end
488
+
428
489
  schema_def_api.factory.new_input_type("DateTimeGroupingOffsetInput") do |t|
429
490
  t.documentation <<~EOS
430
491
  Input type offered when grouping on `DateTime` fields, representing the amount of offset
@@ -619,6 +680,24 @@ module ElasticGraph
619
680
  schema_def_api.scalar_type "String" do |t|
620
681
  t.mapping type: "keyword"
621
682
  t.json_schema type: "string"
683
+
684
+ t.customize_filter_input_type do |fit|
685
+ fit.field names.contains, schema_def_state.type_ref("StringContains").as_filter_input.name do |f|
686
+ f.documentation <<~EOS
687
+ Matches documents using substring filtering.
688
+
689
+ When `null` is passed, matches all documents.
690
+ EOS
691
+ end
692
+
693
+ fit.field names.starts_with, schema_def_state.type_ref("StringStartsWith").as_filter_input.name do |f|
694
+ f.documentation <<~EOS
695
+ Matches documents using prefix filtering.
696
+
697
+ When `null` is passed, matches all documents.
698
+ EOS
699
+ end
700
+ end
622
701
  end
623
702
  end
624
703
 
@@ -953,38 +1032,6 @@ module ElasticGraph
953
1032
  # elasticgraph-graphql/spec/acceptance/elasticgraph_graphql_spec.rb
954
1033
  es_first_day_of_week = "Monday"
955
1034
 
956
- # TODO: Drop support for legacy grouping schema
957
- schema_def_api.enum_type "DateGroupingGranularity" do |t|
958
- t.documentation <<~EOS
959
- Enumerates the supported granularities of a `Date`.
960
- EOS
961
-
962
- t.value "YEAR" do |v|
963
- v.documentation "The year a `Date` falls in."
964
- v.update_runtime_metadata datastore_value: "year"
965
- end
966
-
967
- t.value "QUARTER" do |v|
968
- v.documentation "The quarter a `Date` falls in."
969
- v.update_runtime_metadata datastore_value: "quarter"
970
- end
971
-
972
- t.value "MONTH" do |v|
973
- v.documentation "The month a `Date` falls in."
974
- v.update_runtime_metadata datastore_value: "month"
975
- end
976
-
977
- t.value "WEEK" do |v|
978
- v.documentation "The week, beginning on #{es_first_day_of_week}, a `Date` falls in."
979
- v.update_runtime_metadata datastore_value: "week"
980
- end
981
-
982
- t.value "DAY" do |v|
983
- v.documentation "The exact day of a `Date`."
984
- v.update_runtime_metadata datastore_value: "day"
985
- end
986
- end
987
-
988
1035
  schema_def_api.enum_type "DateGroupingTruncationUnit" do |t|
989
1036
  t.documentation <<~EOS
990
1037
  Enumerates the supported truncation units of a `Date`.
@@ -1016,53 +1063,6 @@ module ElasticGraph
1016
1063
  end
1017
1064
  end
1018
1065
 
1019
- # TODO: Drop support for legacy grouping schema
1020
- schema_def_api.enum_type "DateTimeGroupingGranularity" do |t|
1021
- t.documentation <<~EOS
1022
- Enumerates the supported granularities of a `DateTime`.
1023
- EOS
1024
-
1025
- t.value "YEAR" do |v|
1026
- v.documentation "The year a `DateTime` falls in."
1027
- v.update_runtime_metadata datastore_value: "year"
1028
- end
1029
-
1030
- t.value "QUARTER" do |v|
1031
- v.documentation "The quarter a `DateTime` falls in."
1032
- v.update_runtime_metadata datastore_value: "quarter"
1033
- end
1034
-
1035
- t.value "MONTH" do |v|
1036
- v.documentation "The month a `DateTime` falls in."
1037
- v.update_runtime_metadata datastore_value: "month"
1038
- end
1039
-
1040
- t.value "WEEK" do |v|
1041
- v.documentation "The week, beginning on #{es_first_day_of_week}, a `DateTime` falls in."
1042
- v.update_runtime_metadata datastore_value: "week"
1043
- end
1044
-
1045
- t.value "DAY" do |v|
1046
- v.documentation "The day a `DateTime` falls in."
1047
- v.update_runtime_metadata datastore_value: "day"
1048
- end
1049
-
1050
- t.value "HOUR" do |v|
1051
- v.documentation "The hour a `DateTime` falls in."
1052
- v.update_runtime_metadata datastore_value: "hour"
1053
- end
1054
-
1055
- t.value "MINUTE" do |v|
1056
- v.documentation "The minute a `DateTime` falls in."
1057
- v.update_runtime_metadata datastore_value: "minute"
1058
- end
1059
-
1060
- t.value "SECOND" do |v|
1061
- v.documentation "The second a `DateTime` falls in."
1062
- v.update_runtime_metadata datastore_value: "second"
1063
- end
1064
- end
1065
-
1066
1066
  schema_def_api.enum_type "DateTimeGroupingTruncationUnit" do |t|
1067
1067
  t.documentation <<~EOS
1068
1068
  Enumerates the supported truncation units of a `DateTime`.
@@ -52,6 +52,8 @@ module ElasticGraph
52
52
  # @private
53
53
  # @!attribute [rw] grouped_by_customizations
54
54
  # @private
55
+ # @!attribute [rw] highlights_customizations
56
+ # @private
55
57
  # @!attribute [rw] sub_aggregations_customizations
56
58
  # @private
57
59
  # @!attribute [rw] aggregated_values_customizations
@@ -68,6 +70,8 @@ module ElasticGraph
68
70
  # @private
69
71
  # @!attribute [rw] groupable
70
72
  # @private
73
+ # @!attribute [rw] highlightable
74
+ # @private
71
75
  # @!attribute [rw] source
72
76
  # @private
73
77
  # @!attribute [rw] runtime_field_script
@@ -80,19 +84,16 @@ module ElasticGraph
80
84
  # @private
81
85
  # @!attribute [rw] non_nullable_in_json_schema
82
86
  # @private
83
- # @!attribute [rw] backing_indexing_field
84
- # @private
85
87
  # @!attribute [rw] as_input
86
88
  # @private
87
- # @!attribute [rw] legacy_grouping_schema
88
- # @private
89
89
  class Field < Struct.new(
90
90
  :name, :original_type, :parent_type, :original_type_for_derived_types, :schema_def_state, :accuracy_confidence,
91
- :filter_customizations, :grouped_by_customizations, :sub_aggregations_customizations,
92
- :aggregated_values_customizations, :sort_order_enum_value_customizations,
93
- :args, :sortable, :filterable, :aggregatable, :groupable, :graphql_only, :source, :runtime_field_script, :relationship, :singular_name,
94
- :computation_detail, :non_nullable_in_json_schema, :backing_indexing_field, :as_input,
95
- :legacy_grouping_schema, :name_in_index, :resolver
91
+ :filter_customizations, :grouped_by_customizations, :highlights_customizations, :sub_aggregations_customizations,
92
+ :aggregated_values_customizations, :sort_order_enum_value_customizations, :args,
93
+ :sortable, :filterable, :aggregatable, :groupable, :highlightable,
94
+ :graphql_only, :source, :runtime_field_script, :relationship, :singular_name,
95
+ :computation_detail, :non_nullable_in_json_schema, :as_input,
96
+ :name_in_index, :resolver
96
97
  )
97
98
  include Mixins::HasDocumentation
98
99
  include Mixins::HasDirectives
@@ -104,8 +105,8 @@ module ElasticGraph
104
105
  name:, type:, parent_type:, schema_def_state:,
105
106
  accuracy_confidence: :high, name_in_index: name,
106
107
  type_for_derived_types: nil, graphql_only: nil, singular: nil,
107
- sortable: nil, filterable: nil, aggregatable: nil, groupable: nil,
108
- backing_indexing_field: nil, as_input: false, legacy_grouping_schema: false, resolver: nil
108
+ sortable: nil, filterable: nil, aggregatable: nil, groupable: nil, highlightable: nil,
109
+ as_input: false, resolver: nil
109
110
  )
110
111
  type_ref = schema_def_state.type_ref(type)
111
112
  super(
@@ -117,6 +118,7 @@ module ElasticGraph
117
118
  accuracy_confidence: accuracy_confidence,
118
119
  filter_customizations: [],
119
120
  grouped_by_customizations: [],
121
+ highlights_customizations: [],
120
122
  sub_aggregations_customizations: [],
121
123
  aggregated_values_customizations: [],
122
124
  sort_order_enum_value_customizations: [],
@@ -125,6 +127,7 @@ module ElasticGraph
125
127
  filterable: filterable,
126
128
  aggregatable: aggregatable,
127
129
  groupable: groupable,
130
+ highlightable: highlightable,
128
131
  graphql_only: graphql_only,
129
132
  source: nil,
130
133
  runtime_field_script: nil,
@@ -134,9 +137,7 @@ module ElasticGraph
134
137
  singular_name: singular,
135
138
  name_in_index: name_in_index,
136
139
  non_nullable_in_json_schema: false,
137
- backing_indexing_field: backing_indexing_field,
138
140
  as_input: as_input,
139
- legacy_grouping_schema: legacy_grouping_schema,
140
141
  resolver: resolver
141
142
  )
142
143
 
@@ -179,6 +180,7 @@ module ElasticGraph
179
180
  # @return [void]
180
181
  # @see #customize_aggregated_values_field
181
182
  # @see #customize_grouped_by_field
183
+ # @see #customize_highlights_field
182
184
  # @see #customize_sort_order_enum_values
183
185
  # @see #customize_sub_aggregations_field
184
186
  # @see #on_each_generated_schema_element
@@ -211,6 +213,7 @@ module ElasticGraph
211
213
  # @return [void]
212
214
  # @see #customize_filter_field
213
215
  # @see #customize_grouped_by_field
216
+ # @see #customize_highlights_field
214
217
  # @see #customize_sort_order_enum_values
215
218
  # @see #customize_sub_aggregations_field
216
219
  # @see #on_each_generated_schema_element
@@ -243,6 +246,7 @@ module ElasticGraph
243
246
  # @return [void]
244
247
  # @see #customize_aggregated_values_field
245
248
  # @see #customize_filter_field
249
+ # @see #customize_highlights_field
246
250
  # @see #customize_sort_order_enum_values
247
251
  # @see #customize_sub_aggregations_field
248
252
  # @see #on_each_generated_schema_element
@@ -265,6 +269,39 @@ module ElasticGraph
265
269
  grouped_by_customizations << customization_block
266
270
  end
267
271
 
272
+ # @note For each field defined in your schema that is highlightable, a corresponding highlights field will be created on the
273
+ # `*Highlights` type derived from the parent object type.
274
+ #
275
+ # Registers a customization callback that will be applied to the corresponding highlights field that will be generated for this
276
+ # field.
277
+ #
278
+ # @yield [Field] derived highlights field
279
+ # @return [void]
280
+ # @see #customize_aggregated_values_field
281
+ # @see #customize_filter_field
282
+ # @see #customize_grouped_by_field
283
+ # @see #customize_sort_order_enum_values
284
+ # @see #customize_sub_aggregations_field
285
+ # @see #on_each_generated_schema_element
286
+ #
287
+ # @example Mark `CampaignHighlights.organizationId` with `@deprecated`
288
+ # ElasticGraph.define_schema do |schema|
289
+ # schema.object_type "Campaign" do |t|
290
+ # t.field "id", "ID"
291
+ #
292
+ # t.field "organizationId", "ID" do |f|
293
+ # f.customize_highlights_field do |gbf|
294
+ # gbf.directive "deprecated"
295
+ # end
296
+ # end
297
+ #
298
+ # t.index "campaigns"
299
+ # end
300
+ # end
301
+ def customize_highlights_field(&customization_block)
302
+ highlights_customizations << customization_block
303
+ end
304
+
268
305
  # @note For each field defined in your schema that is sub-aggregatable (e.g. list fields indexed using the `nested` mapping type),
269
306
  # a corresponding field will be created on the `*AggregationSubAggregations` type derived from the parent object type.
270
307
  #
@@ -276,6 +313,7 @@ module ElasticGraph
276
313
  # @see #customize_aggregated_values_field
277
314
  # @see #customize_filter_field
278
315
  # @see #customize_grouped_by_field
316
+ # @see #customize_highlights_field
279
317
  # @see #customize_sort_order_enum_values
280
318
  # @see #on_each_generated_schema_element
281
319
  #
@@ -317,6 +355,7 @@ module ElasticGraph
317
355
  # @see #customize_aggregated_values_field
318
356
  # @see #customize_filter_field
319
357
  # @see #customize_grouped_by_field
358
+ # @see #customize_highlights_field
320
359
  # @see #customize_sub_aggregations_field
321
360
  # @see #on_each_generated_schema_element
322
361
  #
@@ -345,6 +384,8 @@ module ElasticGraph
345
384
  # ask for values for the field in a response.
346
385
  # * A {Field} may be generated on the `*FilterInput` {InputType} derived from the parent {ObjectType} or {InterfaceType}. This is
347
386
  # used by clients to specify how the query should filter.
387
+ # * A {Field} may be generated on the `*Highlights` {ObjectType} derived from the parent {ObjectType} or {InterfaceType}. This is
388
+ # used by clients to request search highlights for a field.
348
389
  # * A {Field} may be generated on the `*AggregationGroupedBy` {ObjectType} derived from the parent {ObjectType} or {InterfaceType}.
349
390
  # This is used by clients to specify how aggregations should be grouped.
350
391
  # * A {Field} may be generated on the `*AggregatedValues` {ObjectType} derived from the parent {ObjectType} or {InterfaceType}.
@@ -361,6 +402,7 @@ module ElasticGraph
361
402
  # @see #customize_aggregated_values_field
362
403
  # @see #customize_filter_field
363
404
  # @see #customize_grouped_by_field
405
+ # @see #customize_highlights_field
364
406
  # @see #customize_sort_order_enum_values
365
407
  # @see #customize_sub_aggregations_field
366
408
  #
@@ -369,15 +411,16 @@ module ElasticGraph
369
411
  # schema.object_type "Transaction" do |t|
370
412
  # t.field "id", "ID"
371
413
  #
372
- # t.field "amount", "Int" do |f|
414
+ # t.field "currency", "String" do |f|
373
415
  # f.on_each_generated_schema_element do |element|
374
- # # Adds a `@deprecated` directive to every GraphQL schema element generated for `amount`:
416
+ # # Adds a `@deprecated` directive to every GraphQL schema element generated for `currency`:
375
417
  # #
376
- # # - The `Transaction.amount` field.
377
- # # - The `TransactionFilterInput.amount` field.
378
- # # - The `TransactionAggregationGroupedBy.amount` field.
379
- # # - The `TransactionAggregatedValues.amount` field.
380
- # # - The `TransactionSortOrder.amount_ASC` and`TransactionSortOrder.amount_DESC` enum values.
418
+ # # - The `Transaction.currency` field.
419
+ # # - The `TransactionFilterInput.currency` field.
420
+ # # - The `TransactionHighlights.currency` field.
421
+ # # - The `TransactionAggregationGroupedBy.currency` field.
422
+ # # - The `TransactionAggregatedValues.currency` field.
423
+ # # - The `TransactionSortOrder.currency_ASC` and`TransactionSortOrder.currency_DESC` enum values.
381
424
  # element.directive "deprecated"
382
425
  # end
383
426
  # end
@@ -390,6 +433,7 @@ module ElasticGraph
390
433
  customize_filter_field(&customization_block)
391
434
  customize_aggregated_values_field(&customization_block)
392
435
  customize_grouped_by_field(&customization_block)
436
+ customize_highlights_field(&customization_block)
393
437
  customize_sub_aggregations_field(&customization_block)
394
438
  customize_sort_order_enum_values(&customization_block)
395
439
  end
@@ -607,6 +651,17 @@ module ElasticGraph
607
651
  nested? || type_for_derived_types.fully_unwrapped.as_object_type&.supports?(&:sub_aggregatable?)
608
652
  end
609
653
 
654
+ # @private
655
+ HIGHLIGHTABLE_MAPPING_TYPES = %w[keyword text match_only_text]
656
+
657
+ def highlightable?
658
+ return highlightable unless highlightable.nil?
659
+ return false if relationship
660
+ return true if HIGHLIGHTABLE_MAPPING_TYPES.include?(mapping_type)
661
+
662
+ type_for_derived_types.fully_unwrapped.as_object_type&.supports?(&:highlightable?)
663
+ end
664
+
610
665
  # Defines an argument on the field.
611
666
  #
612
667
  # @note ElasticGraph takes care of defining arguments for all the query features it supports, so there is generally no need to use
@@ -672,16 +727,32 @@ module ElasticGraph
672
727
  parent_type.field field_name, grouped_by_field_type_name, name_in_index: name_in_index, graphql_only: true do |f|
673
728
  add_grouped_by_field_documentation(f)
674
729
 
675
- define_legacy_timestamp_grouping_arguments_if_needed(f) if legacy_grouping_schema
676
-
677
730
  grouped_by_customizations.each { |block| block.call(f) }
678
731
  end
679
732
  end
680
733
 
734
+ # @private
735
+ def define_highlights_field(parent_type)
736
+ return unless highlightable?
737
+
738
+ unwrapped_type = type_for_derived_types.fully_unwrapped
739
+ type_name =
740
+ if unwrapped_type.leaf?
741
+ "[String!]!"
742
+ else
743
+ unwrapped_type.as_highlights.name
744
+ end
745
+
746
+ parent_type.field name, type_name, name_in_index: name_in_index, graphql_only: true do |f|
747
+ f.documentation derived_documentation("Search highlights for the `#{name}`, providing snippets of the matching text")
748
+ highlights_customizations.each { |block| block.call(f) }
749
+ end
750
+ end
751
+
681
752
  # @private
682
753
  def grouped_by_field_type_name
683
754
  unwrapped_type = type_for_derived_types.fully_unwrapped
684
- if unwrapped_type.scalar_type_needing_grouped_by_object? && !legacy_grouping_schema
755
+ if unwrapped_type.scalar_type_needing_grouped_by_object?
685
756
  unwrapped_type.with_reverted_override.as_grouped_by.name
686
757
  elsif unwrapped_type.leaf?
687
758
  unwrapped_type.name
@@ -702,7 +773,7 @@ module ElasticGraph
702
773
  "The `#{name}` field value for this group",
703
774
  list_field_grouped_by_doc_note("the selected subfields of `#{name}`")
704
775
  )
705
- elsif type_for_derived_types.fully_unwrapped.scalar_type_needing_grouped_by_object? && !legacy_grouping_schema
776
+ elsif type_for_derived_types.fully_unwrapped.scalar_type_needing_grouped_by_object?
706
777
  derived_documentation("Offers the different grouping options for the `#{name}` value within this group")
707
778
  else
708
779
  derived_documentation("The `#{name}` field value for this group")
@@ -936,6 +1007,11 @@ module ElasticGraph
936
1007
 
937
1008
  private
938
1009
 
1010
+ def backing_indexing_field
1011
+ return nil unless graphql_only
1012
+ parent_type.indexing_fields_by_name_in_index[name_in_index]
1013
+ end
1014
+
939
1015
  def args_sdl(joiner:, after_opening_paren: "", &arg_selector)
940
1016
  selected_args = args.values.select(&arg_selector)
941
1017
  args_sdl = selected_args.map(&:to_sdl).flat_map { |s| s.split("\n") }.join(joiner)
@@ -948,40 +1024,6 @@ module ElasticGraph
948
1024
  mapping_type == "text"
949
1025
  end
950
1026
 
951
- def define_legacy_timestamp_grouping_arguments_if_needed(grouping_field)
952
- case type.fully_unwrapped.name
953
- when "Date"
954
- grouping_field.argument schema_def_state.schema_elements.granularity, "DateGroupingGranularity!" do |a|
955
- a.documentation "Determines the grouping granularity for this field."
956
- end
957
-
958
- grouping_field.argument schema_def_state.schema_elements.offset_days, "Int" do |a|
959
- a.documentation <<~EOS
960
- Number of days (positive or negative) to shift the `Date` boundaries of each date grouping bucket.
961
-
962
- For example, when grouping by `YEAR`, this can be used to align the buckets with fiscal or school years instead of calendar years.
963
- EOS
964
- end
965
- when "DateTime"
966
- grouping_field.argument schema_def_state.schema_elements.granularity, "DateTimeGroupingGranularity!" do |a|
967
- a.documentation "Determines the grouping granularity for this field."
968
- end
969
-
970
- grouping_field.argument schema_def_state.schema_elements.time_zone, "TimeZone" do |a|
971
- a.documentation "The time zone to use when determining which grouping a `DateTime` value falls in."
972
- a.default "UTC"
973
- end
974
-
975
- grouping_field.argument schema_def_state.schema_elements.offset, "DateTimeGroupingOffsetInput" do |a|
976
- a.documentation <<~EOS
977
- Amount of offset (positive or negative) to shift the `DateTime` boundaries of each grouping bucket.
978
-
979
- For example, when grouping by `WEEK`, you can shift by 24 hours to change what day-of-week weeks are considered to start on.
980
- EOS
981
- end
982
- end
983
- end
984
-
985
1027
  def list_field_grouped_by_doc_note(individual_value_selection_description)
986
1028
  <<~EOS.strip
987
1029
  Note: `#{name}` is a collection field, but selecting this field will group on individual values of #{individual_value_selection_description}.
@@ -39,7 +39,16 @@ module ElasticGraph
39
39
  # @private
40
40
  # @!attribute [rw] aggregated_values_customizations
41
41
  # @private
42
- class ScalarType < Struct.new(:schema_def_state, :type_ref, :mapping_type, :runtime_metadata, :aggregated_values_customizations)
42
+ # @!attribute [rw] filter_input_customizations
43
+ # @private
44
+ class ScalarType < Struct.new(
45
+ :schema_def_state,
46
+ :type_ref,
47
+ :mapping_type,
48
+ :runtime_metadata,
49
+ :aggregated_values_customizations,
50
+ :filter_input_customizations
51
+ )
43
52
  # `Struct.new` provides the following methods:
44
53
  # @dynamic type_ref, runtime_metadata
45
54
  prepend Mixins::VerifiesGraphQLName
@@ -157,6 +166,13 @@ module ElasticGraph
157
166
  self.aggregated_values_customizations = block
158
167
  end
159
168
 
169
+ # Registers a block which will be used to customize the derived `*FilterInput` object type.
170
+ #
171
+ # @private
172
+ def customize_filter_input_type(&block)
173
+ self.filter_input_customizations = block
174
+ end
175
+
160
176
  # @private
161
177
  def aggregated_values_type
162
178
  if aggregated_values_customizations
@@ -284,6 +300,8 @@ module ElasticGraph
284
300
  f.documentation LTE_DOC
285
301
  end
286
302
  end
303
+
304
+ filter_input_customizations&.call(t)
287
305
  end
288
306
  end
289
307
 
@@ -147,6 +147,7 @@ module ElasticGraph
147
147
  FieldsListFilterInput: "%{base}FieldsListFilterInput",
148
148
  FilterInput: "%{base}FilterInput",
149
149
  GroupedBy: "%{base}GroupedBy",
150
+ Highlights: "%{base}Highlights",
150
151
  InputEnum: "%{base}Input",
151
152
  ListElementFilterInput: "%{base}ListElementFilterInput",
152
153
  ListFilterInput: "%{base}ListFilterInput",
@@ -287,6 +287,7 @@ module ElasticGraph
287
287
  # @dynamic as_edge
288
288
  # @dynamic as_fields_list_filter_input
289
289
  # @dynamic as_filter_input
290
+ # @dynamic as_highlights
290
291
  # @dynamic as_input_enum
291
292
  # @dynamic as_list_element_filter_input, list_element_filter_input?
292
293
  # @dynamic as_list_filter_input, list_filter_input?
@@ -301,7 +301,7 @@ module ElasticGraph
301
301
 
302
302
  schema_def_state.paginated_collection_element_types << element_type
303
303
 
304
- backing_indexing_field = field(name, "[#{element_type}!]!", indexing_only: true, name_in_index: name_in_index, &block)
304
+ field(name, "[#{element_type}!]!", indexing_only: true, name_in_index: name_in_index, &block)
305
305
 
306
306
  field(
307
307
  name,
@@ -311,8 +311,7 @@ module ElasticGraph
311
311
  groupable: !!singular,
312
312
  sortable: false,
313
313
  graphql_only: true,
314
- singular: singular,
315
- backing_indexing_field: backing_indexing_field
314
+ singular: singular
316
315
  ) do |f|
317
316
  f.define_relay_pagination_arguments!
318
317
  block&.call(f)
@@ -31,30 +31,10 @@ if (previousSourceIdsForRelationship.size() > 0) {
31
31
  );
32
32
  }
33
33
 
34
- // While the version in `__versions` is going to be used for the doc version in the future, for now
35
- // we need to continue getting it from `__sourceVersions`. Both our old version and this versions of this
36
- // script keep the value in `__sourceVersions` up-to-date, whereas the old script only writes it to
37
- // `__sourceVersions`. Until we have completely migrated off of the old script for all ElasticGraph
38
- // clusters, we need to keep using it.
39
- //
40
- // Later, after the old script is no longer used by any clusters, we'll stop using `__sourceVersions`.
41
- Number _versionForSourceType = source.get("__sourceVersions")?.get(params.sourceType)?.get(sourceId);
42
- Number _versionForRelationship = relationshipVersionsMap.get(sourceId);
34
+ Number maybeDocVersion = source.__versions.get(params.relationship)?.get(params.sourceId);
43
35
 
44
36
  // Our JSON schema requires event versions to be non-negative, so we can safely use Long.MIN_VALUE as a stand-in when the value is null.
45
- long versionForSourceType = _versionForSourceType == null ? Long.MIN_VALUE : _versionForSourceType.longValue();
46
- long versionForRelationship = _versionForRelationship == null ? Long.MIN_VALUE : _versionForRelationship.longValue();
47
-
48
- // Pick the larger of the two versions as our doc version. Note that `Math.max` didn't work for me here for
49
- // reasons I don't understand, but a simple ternary works fine.
50
- //
51
- // In theory, we could just use `versionForSourceType` as the `docVersion` (and not even check `__versions` at all)
52
- // since both the old version and this version maintain the doc version in `__sourceVersions`. However, that would
53
- // prevent this version of the script from being forward-compatible with the planned next version of this script.
54
- // In the next version, we plan to stop writing to `__sourceVersions`, and as we can't deploy that change atomically,
55
- // this version of the script will continue to run after that has begun to be used. So this version of the script
56
- // must consider which version is greater here, and not simply trust either version value.
57
- long docVersion = versionForSourceType > versionForRelationship ? versionForSourceType : versionForRelationship;
37
+ long docVersion = maybeDocVersion == null ? Long.MIN_VALUE : maybeDocVersion.longValue();
58
38
 
59
39
  if (docVersion >= eventVersion) {
60
40
  throw new IllegalArgumentException("ElasticGraph update was a no-op: [" +
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticgraph-schema_definition
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.2.1
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Myron Marston
@@ -9,7 +9,7 @@ authors:
9
9
  - Block Engineering
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-04-24 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: elasticgraph-graphql
@@ -17,84 +17,84 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 0.19.2.1
20
+ version: 1.0.0.rc1
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - '='
26
26
  - !ruby/object:Gem::Version
27
- version: 0.19.2.1
27
+ version: 1.0.0.rc1
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: elasticgraph-indexer
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - '='
33
33
  - !ruby/object:Gem::Version
34
- version: 0.19.2.1
34
+ version: 1.0.0.rc1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - '='
40
40
  - !ruby/object:Gem::Version
41
- version: 0.19.2.1
41
+ version: 1.0.0.rc1
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: elasticgraph-json_schema
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - '='
47
47
  - !ruby/object:Gem::Version
48
- version: 0.19.2.1
48
+ version: 1.0.0.rc1
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - '='
54
54
  - !ruby/object:Gem::Version
55
- version: 0.19.2.1
55
+ version: 1.0.0.rc1
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: elasticgraph-schema_artifacts
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - '='
61
61
  - !ruby/object:Gem::Version
62
- version: 0.19.2.1
62
+ version: 1.0.0.rc1
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - '='
68
68
  - !ruby/object:Gem::Version
69
- version: 0.19.2.1
69
+ version: 1.0.0.rc1
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: elasticgraph-support
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - '='
75
75
  - !ruby/object:Gem::Version
76
- version: 0.19.2.1
76
+ version: 1.0.0.rc1
77
77
  type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - '='
82
82
  - !ruby/object:Gem::Version
83
- version: 0.19.2.1
83
+ version: 1.0.0.rc1
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: graphql
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: 2.5.4
90
+ version: 2.5.6
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
95
  - - "~>"
96
96
  - !ruby/object:Gem::Version
97
- version: 2.5.4
97
+ version: 2.5.6
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: graphql-c_parser
100
100
  requirement: !ruby/object:Gem::Requirement
@@ -104,7 +104,7 @@ dependencies:
104
104
  version: '1.1'
105
105
  - - ">="
106
106
  - !ruby/object:Gem::Version
107
- version: 1.1.2
107
+ version: 1.1.3
108
108
  type: :runtime
109
109
  prerelease: false
110
110
  version_requirements: !ruby/object:Gem::Requirement
@@ -114,7 +114,7 @@ dependencies:
114
114
  version: '1.1'
115
115
  - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: 1.1.2
117
+ version: 1.1.3
118
118
  - !ruby/object:Gem::Dependency
119
119
  name: rake
120
120
  requirement: !ruby/object:Gem::Requirement
@@ -141,56 +141,56 @@ dependencies:
141
141
  requirements:
142
142
  - - '='
143
143
  - !ruby/object:Gem::Version
144
- version: 0.19.2.1
144
+ version: 1.0.0.rc1
145
145
  type: :development
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - '='
150
150
  - !ruby/object:Gem::Version
151
- version: 0.19.2.1
151
+ version: 1.0.0.rc1
152
152
  - !ruby/object:Gem::Dependency
153
153
  name: elasticgraph-datastore_core
154
154
  requirement: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - '='
157
157
  - !ruby/object:Gem::Version
158
- version: 0.19.2.1
158
+ version: 1.0.0.rc1
159
159
  type: :development
160
160
  prerelease: false
161
161
  version_requirements: !ruby/object:Gem::Requirement
162
162
  requirements:
163
163
  - - '='
164
164
  - !ruby/object:Gem::Version
165
- version: 0.19.2.1
165
+ version: 1.0.0.rc1
166
166
  - !ruby/object:Gem::Dependency
167
167
  name: elasticgraph-elasticsearch
168
168
  requirement: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - '='
171
171
  - !ruby/object:Gem::Version
172
- version: 0.19.2.1
172
+ version: 1.0.0.rc1
173
173
  type: :development
174
174
  prerelease: false
175
175
  version_requirements: !ruby/object:Gem::Requirement
176
176
  requirements:
177
177
  - - '='
178
178
  - !ruby/object:Gem::Version
179
- version: 0.19.2.1
179
+ version: 1.0.0.rc1
180
180
  - !ruby/object:Gem::Dependency
181
181
  name: elasticgraph-opensearch
182
182
  requirement: !ruby/object:Gem::Requirement
183
183
  requirements:
184
184
  - - '='
185
185
  - !ruby/object:Gem::Version
186
- version: 0.19.2.1
186
+ version: 1.0.0.rc1
187
187
  type: :development
188
188
  prerelease: false
189
189
  version_requirements: !ruby/object:Gem::Requirement
190
190
  requirements:
191
191
  - - '='
192
192
  - !ruby/object:Gem::Version
193
- version: 0.19.2.1
193
+ version: 1.0.0.rc1
194
194
  email:
195
195
  - myron@squareup.com
196
196
  executables: []
@@ -275,10 +275,10 @@ licenses:
275
275
  - MIT
276
276
  metadata:
277
277
  bug_tracker_uri: https://github.com/block/elasticgraph/issues
278
- changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.2.1
279
- documentation_uri: https://block.github.io/elasticgraph/api-docs/v0.19.2.1/
278
+ changelog_uri: https://github.com/block/elasticgraph/releases/tag/v1.0.0.rc1
279
+ documentation_uri: https://block.github.io/elasticgraph/api-docs/v1.0.0.rc1/
280
280
  homepage_uri: https://block.github.io/elasticgraph/
281
- source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.2.1/elasticgraph-schema_definition
281
+ source_code_uri: https://github.com/block/elasticgraph/tree/v1.0.0.rc1/elasticgraph-schema_definition
282
282
  gem_category: local
283
283
  rdoc_options: []
284
284
  require_paths:
@@ -287,7 +287,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
287
287
  requirements:
288
288
  - - ">="
289
289
  - !ruby/object:Gem::Version
290
- version: '3.2'
290
+ version: '3.4'
291
291
  - - "<"
292
292
  - !ruby/object:Gem::Version
293
293
  version: '3.5'
@@ -297,7 +297,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
297
297
  - !ruby/object:Gem::Version
298
298
  version: '0'
299
299
  requirements: []
300
- rubygems_version: 3.6.2
300
+ rubygems_version: 3.6.7
301
301
  specification_version: 4
302
302
  summary: ElasticGraph gem that provides the schema definition API and generates schema
303
303
  artifacts.