Schema Migration via GraphQL

Hi, From my testing I’m a bit confused about how to keep Dgraph’s schema in sync with that of a GraphQL schema which I am pushing to Dgraph. I’m trying to work out a workflow for our team such that we can handle both schema and data migrations in a sane way. I watched this excellent video (Data Management with Dgraph) linked in another post but it did not show how to deal with this specific issue. Here is what I’m doing (manually but which will be automated) and seeing.

  1. Starting with a clean Dgraph DB.
  2. Push the following schema to Dgraph using curl -X POST localhost:8080/admin/schema --data-binary '@graphql/schema-1.graphql'
# schema-1.graphql
type Person {
  name: String
}
  1. Resulting Dgraph schema is (taken from Ratel)
<Person.name>: string .
<dgraph.graphql.schema>: string .
<dgraph.graphql.xid>: string @index(exact) @upsert .
  1. and indeed if I query for the GraphQL schema using (installed with npm install -g get-graphql-schema) - $ get-graphql-schema http://localhost:8080/graphql and I get
... lots of good stuff
type Person {
  name: String
}
... lots more good stuff
  1. All good so far!!
  2. Change the schema to the following (nameusername) and push as before
# schema-2.graphql
type Person {
  username: String
}
  1. and the resulting Dgraph schema is now
<Person.name>: string .
<Person.username>: string .
<dgraph.graphql.schema>: string .
<dgraph.graphql.xid>: string @index(exact) @upsert .
  1. Notice that the predicate <Person.name>: string . is still there and so is the new username
  2. query for the GraphQL schema again as before and get
... lots of good stuff
type Person {
  username: String
}
... lots more good stuff

There is no data in the DB, it’s new - I can understand why Dgraph predicates are not removed as they may not be part of the GraphQL schema - so my question is if the schema is being managed purely from the GraphQL schema perspective how would you suggest, from a tooling point of view, managing the synchronisation of these two schemas?

You can do a migration with upsert block e.g:

upsert {
  query {
    v as var(func: has(Person.name)) {
      a as Person.name
    }
  }

  mutation {
    # we copy the values from the old predicate
    set {
      uid(v) <Person.username> val(a) .
    }

    # and we delete the old predicate - this is optional
    delete {
      uid(v) <Person.name> * .
    }
  }
}
2 Likes

Amazing - thank you!!