We have a need to support composite keys in our GraphQL schema to enable having multiple versions of the same object in the db. I.E.
type node {
id: String! @id
version: String! @id
}
Where the determination of uniqueness of a node is the id AND the version. Is this currently a plan on the Dgraph roadmap or possibly another way to support this?
i dont think this has huge priority. because your node is ALWAYS unique. it always has a UID. even if you donât specify that in the schema, it still has under the hood its respective UID (you can even query for it in DQL, even if you dont have it in your schema). it uses UID for the whole graph database thing
the only solution i can suggest you is doing this:
type node {
youruniqueidwithversion: String! @id
}
example value:
youruniqueidwithversion = 43536456_v12.38
BTW: if you have trouble querying in graphql for NESTED values (it is NOT supported in graphql) you gotta use DQL:
{
lots_of_friends(func: ge(count(friend), 2)) @filter(ge(age, 20) AND lt(age, 30)) {
name@.
age
friend {
name@.
}
}
}
@Juri thank you for your response! I dont think using uuids will work for us. As we are using Dgraph in a way to store data that is identifiable outside the system and want to allow users to then query against the Dgraph dababase using values they might already know. i.e. think of a system where we are pulling friendship data from facebook for a schema below
type friend {
name: String! @id
age: String!
}
Dgraph will generate a GraphQL query for getting a friend like so: getFriend(name: '...') {}
As the user making the query will already know the name of the friend they are looking for, this is simple. However, the user will not know of the uuid value generated by Dgraph so if we remove the @id directive from the name field, we will lose the getFriend(name: '...') {} query and it will become getFriend(uuid: '...') {} which is not ideal as the user will not know the relation between a friend and their (dgraph specific) uuid.
I would put forth the argument that support for composite primary keys would be extremely beneficial for use cases where end users are querying the Dgraph DB directly and it is already something supported in SQL and other DB systems.
This will fail on Dgraph insert because it checks each @id field for uniqueness INDIVIDUALLY. This is the main reason for needing composite keys so Dgraph will check uniqueness using multiple @id fields.
This will have the same issue. id: String! @id This field needs to be completely unique. It would also have an issue on this field version: String! @id as imagine you have an array of nodes:
Add the composite string as id__version so that it is forced to be unique. You could use a lambda to enforce this, although if you add it correctly, it will be be unique without a lambda.
The manual composite key makes sense from a logic standpoint but we lose the easy to understand get queries as instead of getNode(name: '..') {} it would be getNode(name_version: '${name}_${version}) {} which the user may not know the version. Thanks for replying!
The uniqueness of the data would be guaranteed by Dgraph would it not? Similar to how the @id field guarantees uniqueness on one field currently. And i see, ok. Would love to see this feature so I hope it can climb the roadmap at some point! thanks for the hard work!
I think this is tracked/requested in Composite @id fields as well. App side concatenating data is possible (usually - you donât always control the client) but annoying and doesnât guarantee the component fields stay in sync w/ the id field after mutations/updates.
Feels like the ID wouldnât be unique. What part of the data would characterize it as unique?
Feels like both nodes are abstractly the same information but with different versions. So, it is the same ânodeâ and the concatenation of the ID with the version makes it unique. Right?
In practice, they arenât unique nodes but it represents an evolution of that data. My question was based on that premise. The uniqueness in the DB itself. This modeling can be done in DQL tho.
So this data example is a response to @jdgamble555 in regards to creating a unique field by concatenating the two fields I want to use as a pair to form uniqueness (a composite key). The field uniqueIdWithVersion would give uniqueness using Dgraphâs current capabilities but would lose some ease of use in regards to the GraphQL generated get* queries Dgraph generates (which is based on the @id fields). You are correct in that the id itself would not be unique. But the composite of {id, version} would be unique which is where this request originated from. Thanks for the further explanation!
@jdgamble555 This is exactly what I am hoping to do! However, I need composite keys because the id and version fields are not unique on their own but only as a pair.
Here is another reason why composite keys like this is close to impossible in Dgraph. This correlates to a very similar question
In Dgraph there you cannot have an index over two predicates because where would the index live if the predicates were not part of the same group. There is a control to manually move predicates to the same group, but if that is not manually done, then it is possible for the two predicates to be distributed across multiple groups (aka servers).
So logically how would you even implement this feature of a unique index across multiple predicates that may be distributed? This would be like saying, it would be like asking SQL to add a unique key constraint across two tables or even two different databases.