Module: ElasticGraph::Apollo::SchemaDefinition::ObjectAndInterfaceExtension

Included in:
InterfaceTypeExtension, ObjectTypeExtension
Defined in:
elasticgraph-apollo/lib/elastic_graph/apollo/schema_definition/object_and_interface_extension.rb

Overview

Instance Method Summary collapse

Instance Method Details

#apollo_entity_ref_field(name, type, id_field_name_in_index:) ⇒ void

Note:

This can be used for either a singleton or list reference, based on if type is a list.

Note:

The resulting field will be only be available for clients to request as a return field. It will not support filtering, sorting, grouping, aggregated values, or highlights.

This method returns an undefined value.

Exposes an Apollo entity reference as a new field, backed by an ID field.

When integrating an ElasticGraph project as a subgraph into a larger Apollo supergraph, it’s useful to be able to reference entities owned by other subgraphs. The most straightforward way to do this is to define an entity reference type (e.g. a type containing just the @key fields such as id: ID and marked as resolvable: false in the @key directive), and then define fields using that type. This approach works particularly well when you plan ahead and know which ID fields to model with entity reference types.

However, on an existing schema where you’ve got some raw ID fields of external entities, it can be quite difficult to replace the ID fields with full-blown entity reference types, as doing so would require migrating clients and running a full backfill.

This API provides an alternate solution for this situation: it defines a GraphQL-only field which returns an entity reference type using a custom GraphQL resolver.

See the Apollo docs on referencing an entity without contributing fields for more information.

Examples:

Expose Review.product and Review.comments entity reference fields

ElasticGraph.define_schema do |schema|
  schema.object_type "Product" do |t|
    t.field "id", "ID"
    t.apollo_key fields: "id", resolvable: false
  end

  schema.object_type "Comment" do |t|
    t.field "id", "ID"
    t.apollo_key fields: "id", resolvable: false
  end

  schema.object_type "Review" do |t|
    t.field "id", "ID"
    t.field "score", "Int"

    # Fields originally defined in the first version of the schema
    t.field "productId", "ID"
    t.field "commentIds", "[ID!]!"

    # New field we're adding to expose the existing `productId` field as a `Product` entity reference.
    t.apollo_entity_ref_field "product", "Product", id_field_name_in_index: "productId"

    # New field we're adding to expose the existing `commentIds` field as a list of `Comment` entity references.
    t.apollo_entity_ref_field "comments", "[Comment!]!", id_field_name_in_index: "commentIds"

    t.index "reviews"
  end
end

Parameters:

  • name (String)

    Name of the field

  • type (String)

    Name of the entity reference type (which must be defined separately)

  • id_field_name_in_index (String)

    Name of the backing ID field in the datastore index

See Also:



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'elasticgraph-apollo/lib/elastic_graph/apollo/schema_definition/object_and_interface_extension.rb', line 74

def apollo_entity_ref_field(name, type, id_field_name_in_index:)
  field(
    name,
    type,
    name_in_index: id_field_name_in_index,
    **LIMITED_GRAPHQL_ONLY_FIELD_OPTIONS
  ) do |f|
    validate_entity_ref_options(__method__.to_s, f, id_field_name_in_index, type) do |exposed_id_field|
      if f.type.list?
        f.resolve_with :apollo_entity_ref_list, source_ids_field: id_field_name_in_index, exposed_id_field: exposed_id_field
      else
        f.resolve_with :apollo_entity_ref, source_id_field: id_field_name_in_index, exposed_id_field: exposed_id_field
      end
    end

    yield f if block_given?
  end
end

#apollo_entity_ref_paginated_collection_field(name, element_type, id_field_name_in_index:) ⇒ void

Note:

This requires id_field_name_in_index to be a list or paginated collection field.

Note:

The resulting field will be only be available for clients to request as a return field. It will not support filtering, sorting, grouping, aggregated values, or highlights.

This method returns an undefined value.

Exposes a collection of Apollo entity references as a new paginated field, backed by an ID field.

When integrating an ElasticGraph project as a subgraph into a larger Apollo supergraph, it’s useful to be able to reference entities owned by other subgraphs. The most straightforward way to do this is to define an entity reference type (e.g. a type containing just the @key fields such as id: ID and marked as resolvable: false in the @key directive), and then define fields using that type. This approach works particularly well when you plan ahead and know which ID fields to model with entity reference types.

However, on an existing schema where you’ve got some raw ID fields of external entities, it can be quite difficult to replace the ID fields with full-blown entity reference types, as doing so would require migrating clients and running a full backfill.

This API provides an alternate solution for this situation: it defines a GraphQL-only field which returns an entity reference type using a custom GraphQL resolver. In contrast to #apollo_entity_ref_field, this defines a field as a paginated Relay connection rather than a simple list.

See the Apollo docs on referencing an entity without contributing fields for more information.

Examples:

Expose Review.product and Review.comments entity reference fields

ElasticGraph.define_schema do |schema|
  schema.object_type "Comment" do |t|
    t.field "id", "ID"
    t.apollo_key fields: "id", resolvable: false
  end

  schema.object_type "Review" do |t|
    t.field "id", "ID"
    t.field "score", "Int"

    # Field originally defined in the first version of the schema
    t.field "commentIds", "[ID!]!"

    # New field we're adding to expose the existing `commentIds` field as a list of `Comment` entity references.
    t.apollo_entity_ref_paginated_collection_field "comments", "Comment", id_field_name_in_index: "commentIds"

    t.index "reviews"
  end
end

Parameters:

  • name (String)

    Name of the field

  • element_type (String)

    Name of the entity reference type (which must be defined separately)

  • id_field_name_in_index (String)

    Name of the backing ID field in the datastore index

See Also:



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'elasticgraph-apollo/lib/elastic_graph/apollo/schema_definition/object_and_interface_extension.rb', line 143

def apollo_entity_ref_paginated_collection_field(name, element_type, id_field_name_in_index:)
  paginated_collection_field(
    name,
    element_type,
    name_in_index: id_field_name_in_index,
    **LIMITED_GRAPHQL_ONLY_PAGINATED_FIELD_OPTIONS
  ) do |f|
    validate_entity_ref_options(__method__.to_s, f, id_field_name_in_index, element_type) do |exposed_id_field|
      backing_indexing_field = f.backing_indexing_field # : ::ElasticGraph::SchemaDefinition::SchemaElements::Field
      unless backing_indexing_field.type.list?
        raise Errors::SchemaError, "`#{f.parent_type.name}.#{f.name}` is invalid: `id_field_name_in_index` must reference an " \
          "id collection field, but the type of `#{id_field_name_in_index}` is `#{backing_indexing_field.type.name}`."
      end

      f.resolve_with :apollo_entity_ref_paginated, source_ids_field: id_field_name_in_index, exposed_id_field: exposed_id_field

      yield f if block_given?
    end
  end
end