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:
- Code generation using a library like json-kotlin-schema-codegen
- Validation in a test suite or at runtime
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.