Schema Updating

I am trying to create an edge between two node types Employees and Employers with the edge name workfor.By following the tutorial as explained here:https://dgraph.io/docs/graphql/schema/graph-links/ .

The Issue I am having is that every time I add the following to my schema using Ratel then click apply schema it says updating.

 type Employees {
workfor: Employer
}

When I reopen Bulk Edit to edit my schema file it now says:

type <Employees> {
	workfor
}

Why does it revert like this and not save the full changes?

You are doing a GraphQL tutorial and Ratel is a DQL UI with no GraphQL support.

Dgraph has two languages. DQL(native one) and GraphQL(an automated API). In order to use GraphQL, you have to use some GraphQL clients. There are a lot of clients out there. For example GraphiQL, Insomnia, Postman, and others.

Okay that makes sense, thank you.

Instead of creating a new thread I am just going to ask this here…

I see that you can manually set a node type using the following command _:a <dgraph.type> "worksfor" .
If I am trying to type thousands of nodes I don’t want to have to manually do this. Am I able to just say "Create edges between all nodes that have a predicate employee and employer"?

Welcome to the Community @ITM007!

I am going to try to translate what you are asking into a logical question that I can answer.

So you have thousands of nodes without types. Some of these nodes are Employers and some of them are Employees. The Employers have a predicate of employee and the Employees have a predicate of employer

This would look something like this datawise:

  <0x1> <employee> <0x2> .
  <0x2> <employer> <0x1> .
  <0x3> <employee> <0x4> .
  <0x4> <employer> <0x3> .

0x1 and 0x3 would be your Employers and 0x2 and 0x4 would be your Employees

Let me know if this is on track. If so, I will continue to answer the question and show how you can use upserts to do this progmatically.


If that isn’t right, then I am thinking you might have a confusion between types, predicates, and edges.

  • Types: https://dgraph.io/docs/query-language/type-system/
  • Predicate: A property of a data node in a graph database; also a discrete piece of information available to request in a graph database.
  • Edge: A relationship between two data nodes in a graph database.

Understanding how data is stored as Triples might help as well: https://dgraph.io/docs/mutations/triples/

If you could post what data you are working with so far, any schema you have posted, and what results you want, we may be able to answer this question better.

If you are new to Dgraph and want a tutorial to follow using DQL then I would recommend: https://dgraph.io/docs/tutorial-1/

This can cause some confusion at first and if you are struggling to get started figuring this out, then let me point you to:

Happy to be apart of the community!

Yes that basically true except my data is in a json format, a watered down comparison can be seen below.

[
    {
    "Employer": "SpaceX",
    "Employees": "john",
    "Hobby": "Fishing",
},

{
    "Employer": "Nasa",
    "Employees": "Alan",
    "Hobby": "Hunting",
},
 ...
thousands of these objects.

That’s why I would like to connect these nodes together with edges based on the information they contain

If the data is not already ingested, I would recommend using a script to convert the data to rdf with blank nodes.

If the data is already ingested then we have to first use a script to create new nodes out of values, then deduplicate the the nodes, and add types. Deduplication the employers may not be that difficult, but deduplicating employees may be next to impossible unless you have a unique identifier. (Two employees named “john” is it the same john that worked at SpaceX?)

I can provide some example scripts later today to show how this would be possible.


This is not a functioning script, just some pseudo code to help you see what is needed to be done.

// query Dgraph to get all Companies and People
data = query(`
  {
    Company (func: has("Employer")) {
      uid
      Employer
    }
    People (func: has(Employees)) {
      uid
      Employees
    }
  }
`)

// create some rdf strings to build upon
addRdf = ''
deleteRdf = ''

data.Companies.each(company => {
  // create a slug that has no spaces or special characters
  slug = company.Employer.slufigy()
  // use the slug as the blank node and set the type to Company
  addRdf += `_:${slug} <dgraph.type> "Company" .\n`
  // set the company name
  addRdf += `_:${slug} <name> "${company.Employer}" .\n`
  // set the workFor edge from the original node to the company
  addRdf += `<${company.uid}> <workFor> _:${slug} .\n`
  // set a inverse edge that the company employs the original node
  addRdf += `_:${slug} <employs> <${company.uid}> .\n`
  // delete the Employer predicate from the original node
  deleteRdf += `<${company.uid}> <Employer> * .\n`
})

data.People.each(person => {
  // set the type of the node to Person
  addRdf += `<${person.uid}> <dgraph.type> "Person" .\n`
  // set the name of the person
  addRdf += `<${person.uid}> <name> "${person.Employees}" .\n`
  // delete the Employees predicate from the person
  deleteRdf += `<${person.uid}> <Employees> * .\n`
})

// send the rdfs to Dgraph in a mutation with the commitNow set to true
mutate({ set: addRdf, delete: deleteRdf }, { commitNow: true })

Here is an example Query that you could make after the above:

{
  People (func: type(Person)) {
    uid
    name
    workFor {
      uid
      name
    }
  }
  Companies (func: type(Company)) {
    uid
    name
    employs {
      uid
      name
    }
  }
}

Then if you wanted to use GraphQL as well, you could set the following GraphQL schema:

type Person {
  id: ID
  name: String @dgraph(pred: "name")
  workFor: [Company] @dgraph(pred: "workFor")
}
type Company {
  id: ID
  name: String @dgraph(pred: "name")
  employs: [Person] @dgraph(pred: "employs")
}

Okay, I see what you are saying. The data is not already ingested. If I understand you correctly I need a script that does two things:

  1. First it needs to convert the json file into an rdf format so that each key - value pair is turned into a node.
  2. And then type the nodes that are created.

When I look through the docs it’s always using small data sets, which makes sense as they are supposed to be easy to view. But why does this seem like it takes so much work? Does every person have to go through all this just to add a medium-size data set (Few thousand line JSON file) to Dgraph and then type it?

If I have dozens of different data sets that I want to create nodes with and then type, it seems like it will be a ton of work. It is most likely that I don’t understand Dgraph but I have read through a lot of the documentation.

For example in the video below using neo4j the person is able to stand up a database with relationships in about 45 minutes. She uses cipher to help organize the data, but I would like to be able to do something similar to this. Do I need to use something like cipher or what?