How ElasticGraph Works

ElasticGraph is a schema-driven framework that helps you build GraphQL APIs backed by Elasticsearch or OpenSearch. Instead of writing boilerplate code, you describe your data model using the schema definition API, and ElasticGraph generates the artifacts needed to power your API.

Here’s how it works.

Schema Definition API

Here’s an example of the schema definition API:

ElasticGraph.define_schema do |schema|
  schema.json_schema_version 1

  schema.object_type "Artist" do |t|
    t.field "id", "ID"
    t.field "name", "String"
    t.field "lifetimeSales", "JsonSafeLong"

    t.field "albums", "[Album!]!" do |f|
      f.mapping type: "nested"
    end

    t.index "artists"
  end

  schema.object_type "Album" do |t|
    t.field "name", "String"
    t.field "releasedOn", "Date"
  end
end

From this schema definition, ElasticGraph generates four different schema artifacts.

Artifact 1: datastore_config.yaml

The datastore_config.yaml artifact contains the full configuration of the datastore (Elasticsearch or OpenSearch) needed to support your API. Here’s a portion of what’s generated from the above schema definition:

---
indices:
  artists:
    aliases: {}
    mappings:
      dynamic: strict
      properties:
        id:
          type: keyword
        name:
          type: keyword
        lifetimeSales:
          type: long
        albums:
          properties:
            name:
              type: keyword
            releasedOn:
              type: date
              format: strict_date
          type: nested

This artifact is used by elasticgraph-admin to administer the datastore, including both initial setup and ongoing maintenance as your schema evolves.

Artifact 2: json_schemas.yaml

The json_schemas.yaml artifact defines the contract between ElasticGraph and the data publisher (that is, whichever system is responsible for publishing data into ElasticGraph) as a JSON schema. Here’s a portion of what’s generated from the above schema definition:

---
"$schema": http://json-schema.org/draft-07/schema#
json_schema_version: 1
"$defs":
  Album:
    type: object
    properties:
      name:
        anyOf:
        - allOf:
          - "$ref": "#/$defs/String"
          - maxLength: 8191
        - type: 'null'
      releasedOn:
        anyOf:
        - "$ref": "#/$defs/Date"
        - type: 'null'
      __typename:
        type: string
        const: Album
        default: Album
    required:
    - name
    - releasedOn

This artifact is designed to be a public artifact. It should be provided to the publishing system, which can use it for:

In addition, elasticgraph-indexer uses a versioned variant of this artifact to validate all data before indexing it into the datastore.

Artifact 3: schema.graphql

The schema.graphql artifact contains the queryable schema as a GraphQL SDL file. It defines the contract between ElasticGraph and your GraphQL clients. The schema defines the query capabilities exposed by ElasticGraph.

Some parts of the GraphQL schema are a direct translation of the types you’ve defined:

type Album {
  name: String
  releasedOn: Date
}

type Artist {
  albums: [Album!]!
  id: ID
  lifetimeSales: JsonSafeLong
  name: String
}

However, most of the schema is composed of derived types. For example, here’s the input ElasticGraph generates to support filtering on Album objects:

input AlbumFilterInput {
  anyOf: [AlbumFilterInput!]
  name: StringFilterInput
  not: AlbumFilterInput
  releasedOn: DateFilterInput
}

This artifact is used by elasticgraph-graphql to provide the GraphQL endpoint. In addition, it’s a public artifact which can be provided to GraphQL clients.

Artifact 4: runtime_metadata.yaml.

The runtime_metadata.yaml artifact is the final schema artifact. It provides metaadata used by the various parts of ElasticGraph at runtime. For example, here’s some of the metadata ElasticGraph records about the Artist type:

---
object_types_by_name:
  Artist:
    graphql_fields_by_name:
      albums:
        resolver: get_record_field_value
      id:
        resolver: get_record_field_value
      lifetimeSales:
        resolver: get_record_field_value
      name:
        resolver: get_record_field_value
    index_definition_names:
    - artists

The runtime metadata provides all of the information needed by the various parts of ElasticGraph to operate at runtime.