How to use set with dgraph when defining string id in graphql

I have a schema defined in graphql:

type User {
  username: String! @id
  isContact: Contact!
}

type Contact {
  id: ID!
  name: String
}

I set some data with dgraph:

{
  set {
    _:user-1 <dgraph.type> "User" .
    _:user-1 <username> "anthony" .
    _:user-1 <isContact> _:user-1C .
    _:user-1C <dgraph.type> "Contact" .
    _:user-1C <name> "Anthony Master" .
  }
}

Response:

{
  "data": {
    "code": "Success",
    "message": "Done",
    "queries": null,
    "uids": {
      "user-1": "0x3b",
      "user-1C": "0x3c"
    }
  },
  "extensions": {
    "server_latency": {
      "parsing_ns": 22700,
      "processing_ns": 258957100,
      "assign_timestamp_ns": 773100,
      "total_ns": 259846600
    },
    "txn": {
      "start_ts": 687,
      "commit_ts": 688,
      "preds": [
        "1-dgraph.type",
        "1-isContact",
        "1-name",
        "1-username"
      ]
    }
  }
}

I can query it with dgraph:

{
  User(func: uid(0x3b)) {
    uid
    username
    isContact {
      uid
      name
    }
  }
}

Response:

{
  "data": {
    "User": [
      {
        "uid": "0x3b",
        "username": "anthony",
        "isContact": [
          {
            "uid": "0x3c",
            "name": "Anthony Master"
          }
        ]
      }
    ]
  },
  "extensions": {
    "server_latency": {
      "parsing_ns": 68400,
      "processing_ns": 97505600,
      "encoding_ns": 51400,
      "assign_timestamp_ns": 817700,
      "total_ns": 98492100
    },
    "txn": {
      "start_ts": 692
    },
    "metrics": {
      "num_uids": {
        "": 1,
        "_total": 6,
        "isContact": 1,
        "name": 1,
        "uid": 2,
        "username": 1
      }
    }
  }
}

But if I try to query the same data with graphql (on the 8080 port /graphql where I can read the schema…):

{
  queryUser {
    username
    isContact {
      id
      name
    }
  }
}

I get the following response error:

{
  "errors": [
    {
      "message": "Non-nullable field 'username' (type String!) was not present in result from Dgraph.  GraphQL error propagation triggered.",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ],
      "path": [
        "queryUser",
        0,
        "username"
      ]
    }
  ],
  "data": {
    "queryUser": [
      null
    ]
  }
}

Can I not set data with dgraph mutations and then read it with graphql queries?

I have a lot of linking data in ~250Mb dataset that I need to import and link together with nodes dependent on nodes and the best method seems to use dgraphs set function with named nodes as above (but more complex in use case)

Hi @amaster507,
Can you check if you set the following schema, does that work for you?

{
  set {
    _:user-1 <dgraph.type> "User" .
    _:user-1 <dgraph.username> "anthony" .
    _:user-1 <dgraph.isContact> _:user-1C .
    _:user-1C <dgraph.type> "Contact" .
    _:user-1C <dgraph.name> "Anthony Master" .
  }
}

Interchanging between using graphql± and graphql has some caveats. When you set types, relationships via graphql, they are internally stored as dgraph.relationship. Therefore I think when you query using graphql, it is unable to find them. Tagging @abhimanyusinghgaur to confirm.

1 Like

Hi @amaster507,

Just to clarify, one should not be mixing graphql± with GraphQL. For example, in your case, you have @id on username, GraphQL will respect it, but graphql± won’t unless you write a correct upsert mutation for it. It is expected that you would either be using GraphQL or graphql± as the query language of your choice, not both of them together. They have their own capabilities, like GraphQL has got interfaces but ± doesn’t. On the other hand, graphql± allows you to write your own queries, while in GraphQL you can only use one of the pre-defined queries.

But, if you really want to use both of them together, then this is the mutation for your case:

{
  set {
    _:user-1 <dgraph.type> "User" .
    _:user-1 <User.username> "anthony" .
    _:user-1 <User.isContact> _:user-1C .
    _:user-1C <dgraph.type> "Contact" .
    _:user-1C <Contact.name> "Anthony Master" .
  }
}
1 Like

The combination of GraphQL± and GraphQL is becoming more enabled as we move forward.

For example, custom resolvers means you can define a field or query or mutation as implemented by code that calls back to GraphQL± for cases where more logic is needed - for example if some pre-checks are needed for a mutation, or you want to use the ± uspert mutations.

As @abhimanyusinghgaur pointed out though, you are seeing a bit more of a raw view of the graph there, so you’ll have to manage things like types and id’s yourself if you do that.

1 Like

I am understanding this dgraph setup a little better now. I will primarily use graphql for mutation and querying data. I believe the new custom directives in the schema will solve much of the features that we need. I want to use dgraph only when importing mass data because it seems simpler to make 3+ way relations on import that doesn’t seem possible with simple graphql generated mutations. (Use case: linking a single email node to a user node and a contact node at the same time)

Yes, there is no bulk import specifically designed from GraphQL - do it through the bulk loader or the live loader. You’ll just have to make sure the data is in the right shape for your GraphQL API. I think we should add some more docs about this as I expect it’ll be a common use case.

Not sure what’s missing for you on the 3-way GraphQL mutations though, because you can do multiples. If you could clarify with an example, that’d help me understand.

Well, I will leave out the hundreds of lines for the example and put it use case.

All in a single import…

Import 550+ users
Create a contact record for each user
Link meta data to the user and the contact
Import 25K contacts which also need to be linked to their creator (user)
Import meta data for those 25K contacts
Import 15K calendar events linked with the attending contacts
Import 95K tasks and activity logs linked to users, events, and/or contacts

So there are many complicated links with this import and it is nice with dgraph not having to know the ids but rather use the blank node variable convention to make the links needed anywhere in the very long generated script.

Converting a 2 year running web app system to this to make it last for another 10 years hopefully without needing to rebuild it again for new features and growth.