Why does it still exist after deleting the node? It has not really been deleted

My schema:

type User {
  name
  username
  ...
}
name: string @index(hash) .
username: string @index(hash) .
...

I want to delete some user. I want to delete the entire node, not certain values:

{
  "delete": [
      { "uid": "0xea61" },
      { "uid": "0xea62" },
      { "uid": "0xea63" }
  ]
}

It executed successfully:

{
  "data": {
    "code": "Success",
    "message": "Done",
    "queries": null,
    "uids": {}
  },
  "extensions": {
    "server_latency": {
      "parsing_ns": 56093,
      "processing_ns": 8551567,
      "assign_timestamp_ns": 1495159,
      "total_ns": 10167730
    },
    "txn": {
      "start_ts": 560080,
      "commit_ts": 560081,
      "preds": [
        "1-dgraph.type"
      ]
    }
  }
}

But it is strange that these data still exist, they have not been deleted. I can still query them:

{
  "data": {
    "user": [
      {
        "uid": "0xea61",
        "username": "mayun"
      },
      {
        "uid": "0xea62",
        "name": "jack",
        "username": "mayun"
      },
      {
        "uid": "0xea63",
        "name": "jack",
        "username": "mayun"
      },
      {
        "uid": "0xea64",
        "name": "jack",
        "username": "mayun"
      }
    ]
  }
}

I use the latest version of dgraph.

I tried using tuple:

{
  delete {
     <0xea61> * * .
  }
}

But the same result is obtained, these data are not really deleted.

Hi @pandalive, thanks for reaching out to us with above issue.

Can you list down the steps to reproduce above issue? Also please tell us exact version of Dgraph you are using.

It is important to note that delete works only if you have a well-defined Type Schema and your dataset has the corresponding <dgraph.type> predicate. If either is not correct, the delete will not work.

Cheers.

@MichelDiz dgraph.type does not exist, I don’t know how to set it.
I checked the documentation description:

{
  set {
    _:a <name> "Garfield" .
    _:a <dgraph.type> "Pet" .
    _:a <dgraph.type> "Animal" .
  }
}

I am confused about this.
Do I need to manually set dgraph.type in Ratel?
Why is dgraph.type not automatically generated when set schema?
If dgraph.type can be generated automatically when set schema, what should I do?
Sorry i am new to dgraph, dgraph’s documentation is bad for me.
This is like telling me a point instead of a course of action. I don’t know where to go.

You can fix this using Upsert Block

This example is called “Bulk upsert” cuz it uses HAS function and therefore, it will add the value in all nodes that has* username predicate. You can use the same logic to any other entities you have.

upsert {
  query {
     v as uid  q(func: has(username))
  }

  mutation {
    set {
      uid(v) <dgraph.type> "User" .
    }
  }
}

The Schema doesn’t touch your dataset at any moment. That’s why.

Does this mean that when I add a new schema, I need to manually set dgraph.type? Can you provide specific steps in the documentation?

dgraph.type seems to be necessary, so it should be generated when set schema.

If you have new data coming from an external source (if the data comes from an application that you created specifically for Dgraph, you should always add the type via application) so yes. You have to add manually or use bulk upsert so.

Some references
https://dgraph.io/docs/query-language/#type-definition
https://dgraph.io/tour/basic/3/

Yes, it is mandatory.

PS. You can create Types in upfront using the /alter endpoint or the Bulk Edit in Ratel. But that is a bit unnecessary. So it is mandatory to have your dataset sanitized first, then you can create the Types in your schema. Use the Bulk Upsert to sanitized it and then add your type.

I have no additional data, I built the dgraph database from scratch. I wrote some schemas, it contains the type, just like the code I posted above. Under normal circumstances, I should not need to do extra things to use the delete feature, which is the basic feature of each database.

Do I have to add dgraph.type attribute when create node ?

Yes, as I said, it is mandatory. Otherwise, the delete won’t work. Sorry but is how it works.

I think dgraph.type should be automatically generated when creating node, which is the same as uid.

Not possible, there’s no way to Dgraph guess what type is some node/entity without someone mark it as a specific type. Unless we add AI somehow and standardize it and also teach how it behaves. Which in a way could add an unwanted level of complexity, possible errors and it increases the latency processing things. In fact, it is an unviable hypothesis in Dgraph’s scope.

Imagine that a dataset can have several (10 up to 10k) types. There’s no way to tell what is what without a human.

So, in your code, you have hardcode the type based on your business model.

I understand that it is a kind of different way to work, but you get used to it. Even for me, months ago (a year? I guess) was a bit strange, but once I noticed it, it just flows.

Cheers.

In fact, something like that would be possible. I was thinking about “strict” mode. Which lets the user mutate only if all given predicates exist in the schema. However, this is not technically “guess the type”. But it would be a way to reinforce the user to write mutations according to the schema.

Enforce a strict schema by setting --mutations strict.

The “strict” mode is not based on Types. But it may be feasible to do so. And also add “dgraph.type” automatically if all predicates(or some) belong to that type.

PS. And there would be cases where two Types share similar predicates. That would be complicated to deal with. Let’s say there are 4 types with the predicate “name”. Dgraph could accidentally assign this node with pred “name” to 4 types.

This approach it is not friendly, but it is according to what you want. But it would not be a default mode. Just like Strict mode is not set by default.

I have created this ticket based on this topic

This is indeed a complicated task.

I am curious, how is GraphQL implemented? GraphQL does not ask for dgraph.type, it seems to do all this automatically.

I really like the GraphQL schema definition. Each type is defined independently, and there is no shared field, unless you use interface. And field and type are not separated, which is good.

type Product {
    id: ID!
    name: String @search(by: [term])
    username: String @search(by: [term])
}

In contrast to GraphQL, the schema definition of GraphQL± makes people look strange.

type Product {
    name
    username
}
name: string @index(hash) .
username: string @index(hash) .

This results in almost every field type being ambiguous, so dgraph.type must be specified, which is bad.

Is there any plan to migrate the GraphQL± schema definition mode to GraphQL?

The GraphQL feature is very different from Dgraph. It is like a “framework”. It creates CRUD operations. Like the mutation one, that is generated automatically, and it is tided to the Type internally. that’s why you don’t have to use <dgraph.type>.

Take Dgraph and GraphQL+- as “RAW”. To have the same behavior from Dgraph’s GraphQL, you have to mount your own API with your own business logic.

Nope, as far as I know both will continue to co-exist. As GraphQL specs don’t cover all GraphQL+- features.