Dql mutation add duplicate records

I’ve added this question to stackoverflow for anyone want to answer dgraph - Dql mutation add duplicate records - Stack Overflow

What I want to do

Prevent the dql mutation to add duplicates records

What I did

I add a graphql schema:

type Product {
    id: ID!
    name: String! @id @dgraph(pred: "Product.name")
    slug: String! @id @dgraph(pred: "Product.slug")
    image: String @dgraph(pred: "Product.image")
    created_at: DateTime! @dgraph(pred: "Product.created_at")
    updated_at: DateTime! @dgraph(pred: "Product.updated_at")
}

the above graphql schema has generated the bellow DQL schema:

<Product.created_at>: datetime .
<Product.image>: string .
<Product.name>: string @index(hash) @upsert .
<Product.slug>: string @index(hash) @upsert .
<Product.updated_at>: datetime .
<dgraph.drop.op>: string .
<dgraph.graphql.p_query>: string @index(sha256) .
<dgraph.graphql.schema>: string .
<dgraph.graphql.xid>: string @index(exact) @upsert .
type <Product> {
	Product.name
	Product.slug
	Product.image
	Product.created_at
	Product.updated_at
}
type <dgraph.graphql> {
	dgraph.graphql.schema
	dgraph.graphql.xid
}
type <dgraph.graphql.persisted_query> {
	dgraph.graphql.p_query
}

I run a mutation to add some data using: https://github.com/dgraph-io/dgo#running-a-mutation.
But it does not respect the @id added to the schema to some fields like “slug” and “name”.

Using the graphql mutation this is working and respect the uniqueness by returning an error:
"message": "couldn't rewrite mutation addProduct because failed to rewrite mutation payload because id aaaa already exists for field name inside type Product"

Dgraph metadata

dgraph version v21.03.2

You can’t mix the same logic of GraphQL with DQL. GraphQL works in a way almost “automatic” and DQL is “by hand”. No DQL query or mutation will check any GraphQL logic. You have to build an Upsert Query based on the GraphQL logic. So it would kind of “respect” the GraphQL data modeling.

so I have to manually check by running a query https://github.com/dgraph-io/dgo#running-a-query first?

wouldn’t be better for dql to also prevent adding duplicate records. In my opinion this is very bad about data integrity!

Well, you should Pick only GraphQL if you are using GraphQL and you will have these guarantees. For DQL, an Upsert Logic should be fine. We have DQL working like this for years. Just a few people complained about it in 4 years and once they learned how to, they get used to it.

The Upsert logic is
1 - A Block to check the existing data. And use variables to capture that info.
2 - A Block to mutate the data based on the data within the variables.

With Upsert Block you can do any complex logic to avoid duplicates - check the docs for more https://dgraph.io/docs/mutations/upsert-block/#sidebar

PS. You have also to pay attention to the Data Modeling in GraphQL. Which is standardized for GraphQL’s context. Mean, the mutation modeling has its rules. You may find them on docs or here in the community posts. In DQL the data modeling is completely free to model.

1 Like

Think of this GraphQL implementation like GraphQL on top of the likes of DynamoDB or MongoDB in that there are not very many rules at all that DQL has to follow, but this is better than any of those options because it then builds the API rules into a single layered db/api. So it is the somewhat best of both worlds but uniquely its own.

2 Likes

In a simple analogy: GraphQL is to Samurai(bureaucracy and honor the types) as DQL is to Ninja(work in the shadows and does tricks freely - also “With great power, there must also come great responsibility” as said Stan Lee).

“Master both languages, you have, to great warrior be” Grand Master Yoda on Dgraph.

Just kidding :stuck_out_tongue: but serious.

2 Likes

And perhaps Stan Lee built his quote from Winston Churchill who said:

Where there is great power there is great responsibility.

Just like DQL was built from Badger… :man_superhero:

2 Likes

Guys, thanks a lot for your replies.

That’s why I use both, because I need the great power of dql and the graphql for the front-end