Dgraph: Support UUIDs in Dgraph

Created on 17 Feb 2017  路  14Comments  路  Source: dgraph-io/dgraph

Hi guys,

I'm considering Dgraph as a graph-handling addition to the current primary db and we already have ids (UUID v4) for all objects, so naturally I would like to have the same keys in DGraph and looks like I won't need uids at all.
My concern is a statement that you do not recommend using external ids.
I believe we will have a certain performance hit because not using dgraph's uids and (maybe) having to lookup on a non-primary key, but frankly not sure how xids work - could you please elaborate on any issue I may have looking up dgraph objects by my own ids instead of uids?

Thank you!
Dennis

P.S.
I believe this may be categorized as "documentation" request.

Most helpful comment

Was this improvement dropped?

It'd be immensely useful to not need to query beforehand the uids of possibly hundreds of nodes before doing a mutation.
Mutating nodes by their XID (unique to the user logic) would then only be one roundtrip and would spare the potentially expensive query.

All 14 comments

Hey @mpmlj ,

Yeah, instead of using UUIDs as external id, you can have an extra edge, which stores UUID, and index it. That way, you can still search for nodes via UUID, but Dgraph would also allocate its own IDs which would be unique, without any concerns about collisions.

For e.g., You can do this:

mutation { set {
  _:node <uuid> "123e4567-e89b-12d3-a456-426655440000" .
}}

Index it using a schema which contains this line:

uuid: string @index(exact)

And then query it like so:

{
  node(eq(uuid, "123e4567-e89b-12d3-a456-426655440000")) {
    stuff
  }
}

Does this help? We'll add this to documentation as well.

I am using this method as well right now. It works, there is only one real issue this way. writes are not idempotent anymore. Running this twice result in 1 write,

mutation{
set{
<0x01> <objectId> "UUID" .
}
}

But running this twice, will result in two nodes, each having an edge UUID

mutation{
set{
_:myId <objectId> "UUID" .
}
}

or we need variables mixed (is this possible?) .....

{
  var A (node(eq(uuid, "123e4567-e89b-12d3-a456-426655440000")) {
    stuff
  })
}
mutation {
set {
<id(A)> <objectId> "UUID"
}
}

We do need a solution to this problem. What @AndreSteenbergen, you're proposing is in the right direction, but not currently possible the way we do mutations (they happen before queries). Also, any solution that we implement, won't be transactional. Needs more thought.

Here's another thought: If all your ids are UUID, then you can safely send mutations with them as XIDs, without any worries about collisions (unique strings will with very high probability convert to unique int64s). If you then allocate new entities in Dgraph, they'd know about these allocated ids (we keep track of used ids) , and allocate new ones.

OK I am actually doing this, because of the same statements @mpmlj refers to, not to depend on xid

I am event sourcing my app, I only have UUID's in the system

+1 to what @AndreSteenbergen is suggesting, I am also looking for something similar where I can find an existing node in graph and create new edge / predicate from it to new node inside mutation block.

This is a frequently requested feature, we'll build it with priority.

I think instead of doing something specifically for UUIDs; we should just support XIDs again. We used to support them but dropped them during the move to Raft.

we support xid natively now. Each xid would be assigned an unique uid internally.

Hey @janardhan1993 , just to update the issue, it can be said that xid is not supported, right? As in https://github.com/dgraph-io/dgraph/releases/tag/v0.9.0 it's stated:

Dgraph live no longer stores external ids. And hence the xid flag is gone.

xids are no longer automatically inserted by dgraph live. xids are now just like any other predicate -- if you add them to your data set, they can be added.

Was this improvement dropped?

It'd be immensely useful to not need to query beforehand the uids of possibly hundreds of nodes before doing a mutation.
Mutating nodes by their XID (unique to the user logic) would then only be one roundtrip and would spare the potentially expensive query.

Yes, xid was given special treatment earlier hence we have dropped it. It is like any other string predicate now. We plan to support openCypher which along with the uniqueness constraint should give you what you are looking for.

For people still looking for a solution, given that upsert block is now available in v1.1.0, the mutation can be ensured to be idempotent.

When an update is not required if the node exists -

upsert {
  query {
    node as var(func: eq(uuid, "123e4567-e89b-12d3-a456-426655440000")
  }

  mutation @if(eq(len(node), 0))) {
    set {
      uid(node) <uuid> "123e4567-e89b-12d3-a456-426655440000" .
    }
  }
}

If overwritting the data is acceptable, just remove the @if condition.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ShawnMilo picture ShawnMilo  路  4Comments

andrewsmedina picture andrewsmedina  路  4Comments

jeffkhull picture jeffkhull  路  3Comments

mbudge picture mbudge  路  3Comments

KadoBOT picture KadoBOT  路  5Comments