# Using a GraphQL Schema + Live Loader to ingest data

**URL:** <https://discuss.dgraph.io/t/using-a-graphql-schema-live-loader-to-ingest-data/14846>\
**Category:** GraphQL\
**Created:** [July 6, 2021, 7:54pm UTC](https://discuss.dgraph.io/t/using-a-graphql-schema-live-loader-to-ingest-data/14846 "2021-07-06T19:54:34Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![pmuens](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pmuens/32/8540_2.png) [@pmuens](https://discuss.dgraph.io/u/pmuens)\
**Post date:** [July 6, 2021, 7:54pm UTC](https://discuss.dgraph.io/t/using-a-graphql-schema-live-loader-to-ingest-data/14846/1 "2021-07-06T19:54:34Z")

</div>

Hey there,  
not sure if this is the right category but I’ll give it a shot.

I’m currently using Dgraph solely via a GraphQL Schema, meaning that I have a `schema.graphl` file which looks something like this:

```auto
type Person {
  id: ID!
  slug: String! @id
  firstName: String!
  lastName: String!
  posts: [Post] @hasInverse(field: author)
}

type Post {
  id: ID!
  slug: String! @id
  author: Person
}

# ... Other type definitions

```

Spinning up Dgraph and mutating / querying via the GraphQL endpoint works flawlessly.

However given that I have a lot more data to ingest, inserting it via GraphQL mutations isn’t feasible. Live Loader seems to be the correct option here. In particular I need to rely on the `--upsertPredicate` option to ensure that re-runs won’t overwrite the already present data in the future.

I followed the docs in [https://dgraph.io/docs/deploy/fast-data-loading/live-loader/](https://dgraph.io/docs/deploy/fast-data-loading/live-loader/) but I just can’t make the connection between the `upserPredicate` example and the GraphQL Schema I wrote.

After fiddling around a little bit I came up with this `data.rdf` file:

```auto
<jdoe> <Blockchain.slug> "jdoe" .
<jdoe> <Blockchain.firstName> "John" .
<jdoe> <Blockchain.lastName> "Doe" .
<jdoe> <dgraph.type> "Person" .

```

I can now run this script via the following Live Loader command: `dgraph live --files data.rdf --upsertPredicate "Person.slug"`

It will only ever create one node given that the `slug` is used as the `--upsertPredicate`.

Now the downside is that this only works because I prefixed `slug` with `Person` (`Person.slug`) which means that there’s no way to have a single `.rdf ` file with multiple different types in it while still using the `--upsertPredicate` flag that way.

Can someone please explain how Live Loader should be used with an existing GraphQL Schema and the `--upsertPredicate` flag (a full example with edges between nodes would be super helpful!)?

Is using the `slug` fine or should I add `xid` to the GraphQL types? Is `xid` just a convention one should follow to provide own ids or is it relied upon by Dgraph internally?

And what’s the difference between:

```auto
<foobar>
<_:foobar>
_:foobar

```

Thanks a lot for working on Dgraph and taking the time to answer this question!

---

<div class="post-metadata">

**Author:** ![pmuens](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pmuens/32/8540_2.png) [@pmuens](https://discuss.dgraph.io/u/pmuens)\
**Post date:** [July 7, 2021, 7:34am UTC](https://discuss.dgraph.io/t/using-a-graphql-schema-live-loader-to-ingest-data/14846/2 "2021-07-07T07:34:49Z")

</div>

After spending more time searching through this forum and the docs I was finally able to figure out a way to use Live Loader in combination with a GraphQL-based schema.

As @pshaddel pointed out in [How do you go from GraphQL to RDF for bulk loading?](http://discuss.hypermode.com/t/how-do-you-go-from-graphql-to-rdf-for-bulk-loading/14830) you can specify the type and predicate names in the GraphQL Schema.

See the documentation here: [https://dgraph.io/docs/graphql/dgraph/#mapping-graphql-to-a-dgraph-schema](https://dgraph.io/docs/graphql/dgraph/#mapping-graphql-to-a-dgraph-schema)

Based on that I came up with the following solution.

The GraphQL Schema:

```auto
type Person {
  id: ID!
  xid: String! @id @dgraph(pred: "xid")
  slug: String! @id
  firstName: String!
  lastName: String!
  posts: [Post] @hasInverse(field: author)
}

type Post {
  id: ID!
  xid: String! @id @dgraph(pred: "xid")
  slug: String! @id
  author: Person
}

```

The `.rdf` file:

```auto
<person/jdoe> <Person.slug> "jdoe" .
<person/jdoe> <Person.firstName> "John" .
<person/jdoe> <Person.lastName> "Doe" .
<person/jdoe> <dgraph.type> "Person" .
<person/jdoe> <xid> "person/jdoe" .

<post/post-1> <Post.slug> "post-1" .
<post/post-1> <dgraph.type> "Post" .
<post/post-1> <xid> "post/post-1" .

<post/post-1> <Post.author> <person/jdoe> .

```

If I now run `dgraph live --files data.rdf --upsertPredicate "xid"` everything gets inserted accordingly. Running the command multiple times doesn’t insert the data multiple times (given that we’re using the `xid` to uniquely identify it).

TBH I’m not entirely sure why this works (especially why I have to use the `xid` as a Node’s subject like `<post/post-1>`) but it does what it should do.

Would be awesome if someone from the Dgraph team could chime in if this is the best practice to accomplish this task. Thanks in advance!

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [July 7, 2021, 4:22pm UTC](https://discuss.dgraph.io/t/using-a-graphql-schema-live-loader-to-ingest-data/14846/3 "2021-07-07T16:22:49Z")

</div>

> [@pmuens](#):
>
> `<person/jdoe>`

This syntax is a bit dangerous for the parser. You lucky cuz the upsertPredicate feature is new and probably works before the parser being run. You should use `<_:person/jdoe>` instead.

> [@pmuens](#):
>
> TBH I’m not entirely sure why this works

The feature upsertPredicate creates several upsert blocks under the hood. Based on the blank node used. And if the blank node is stored in the XID predicate. It will upsert correctly. That’s all.

---

<div class="post-metadata">

**Author:** ![pmuens](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pmuens/32/8540_2.png) [@pmuens](https://discuss.dgraph.io/u/pmuens)\
**Post date:** [July 7, 2021, 7:24pm UTC](https://discuss.dgraph.io/t/using-a-graphql-schema-live-loader-to-ingest-data/14846/4 "2021-07-07T19:24:51Z")

</div>

I see. That makes sense. Thanks for taking the time to reply.

Just a quick follow-up question: Is using `xid: String! @id @dgraph(pred: "xid")` on every GraphQL type in combination with the `--upsertPredicate "xid"` the correct approach / workaround here?

Overall this might be personal preference, but I just want to make sure that I’m not following bad practices when there’s a better solution.

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [July 7, 2021, 7:30pm UTC](https://discuss.dgraph.io/t/using-a-graphql-schema-live-loader-to-ingest-data/14846/5 "2021-07-07T19:30:40Z")

</div>

> [@pmuens](#):
>
> the correct approach / workaround here?

I don’t see any problem.

> [@pmuens](#):
>
> I’m not following bad practices when there’s a better solution

Well, I’m not the guy to recommend best practices in GraphQL. But looks like it won’t be a problem. And If you follow the docs, you’re good to go.

I can cover you 99% DQL and 60% GraphQL(I mean, Dgraph’s features) with my Knowledge. If you still need someone to rectify it I can ping for u.

---

<div class="post-metadata">

**Author:** ![pmuens](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pmuens/32/8540_2.png) [@pmuens](https://discuss.dgraph.io/u/pmuens)\
**Post date:** [July 8, 2021, 3:50pm UTC](https://discuss.dgraph.io/t/using-a-graphql-schema-live-loader-to-ingest-data/14846/6 "2021-07-08T15:50:05Z")

</div>

> I don’t see any problem.

Awesome. Thanks for confirming.

> If you still need someone to rectify it I can ping for u.

All good. Thanks for the offer and taking the time to reply here.
