Graphql-engine: Relay querying by id

Created on 10 Jun 2020  路  14Comments  路  Source: hasura/graphql-engine

Hasura's where clauses in relay only accept the database id, and not the relay id.

This causes a bunch of issues around querying.

If I want to get a project by the id. I must use the node interface instead of the project_connection interface. This means I lose a bunch of auto-complete that's built into different IDEs because they no longer know the data structure that is being returned.

If I want to find all assignments by the project id, I can not query assignments_connection(where: {project_id: {_eq: }}) because it only accepts the database id and not the relay id.

When you are using relay on the frontend, you should only have to worry about the id relay uses. Not try to decipher the database ids.

relay server

Most helpful comment

How could you guys add the record to Relay Store after mutation, I stuck at retrieving the edge from the server response.

mutation CreateTaskMutation($input: task_insert_input!) {
        insert_task_one(object: $input) {
          id
          title
          due_date
          due_time
          description
        }
      }

I got the server response from store.getRootField

const serverResponse = store.getRootField('insert_task_one')

Then how to retrieve the edge? There is no nesting after insert_task_one in that GraphQL query.

const serverEdge = payload.getLinkedRecord(WHAT_SHOULD_I_PUT_HERE);

How to get the edge from the response so I can write to the Relay Store later with ConnectionHandler.insertEdgeAfter()?

Thanks :)

All 14 comments

Is there a work-around for this that doesn't require the client to deal with any database IDs?

If not, can someone tell me (or point me to relevant code) how relay IDs are transformed into types/IDs (and vice-versa)?

Never mind, I see that the relay IDs are base64-encoded arrays. For anyone curious, just base64-decode a few IDs and you'll see how they are structured.

How could you guys add the record to Relay Store after mutation, I stuck at retrieving the edge from the server response.

mutation CreateTaskMutation($input: task_insert_input!) {
        insert_task_one(object: $input) {
          id
          title
          due_date
          due_time
          description
        }
      }

I got the server response from store.getRootField

const serverResponse = store.getRootField('insert_task_one')

Then how to retrieve the edge? There is no nesting after insert_task_one in that GraphQL query.

const serverEdge = payload.getLinkedRecord(WHAT_SHOULD_I_PUT_HERE);

How to get the edge from the response so I can write to the Relay Store later with ConnectionHandler.insertEdgeAfter()?

Thanks :)

Both of these issues are important to me as well. I've managed to work around the former by doing ID -> PK decoding on the client, but it doesn't feel great. However, the mutation responses not including the edge makes writing updater configs impossible (as far as I can tell).

Not impossible, you just have to create the edge by yourself, I haven't done that because now I need to know how to construct a relay style id (the one they use to store item in RelayStore), and TBH, I use Relay experimental and I have no idea.

The team is working on that, so I will wait until the next release, my project is current in dev, so the optimistic update can be leaved later

I'm not sure how that would work, actually. I'm talking specifically about using the updater configs method for updates.

+1 - this is a problem for our team too. I suggest going with Postgraphile's strategy of naming the Relay id "nodeId" to avoid conflicts with "id" fields in tables: https://www.graphile.org/postgraphile/node-id/

I could be mistaken, but I think calling it nodeId breaks Relay's expected schema https://relay.dev/docs/en/graphql-server-specification.html#object-identification

The Node interface contains a single field, id, which is an ID!

I'm also running into this problem. I like @crieggalder 's idea of doing what PostGraphile does and calling it nodeId.

also having this issue. Here is my current work around:

export const validateUUID = (base64StringOrUuidd) => { try { // base64 string decodes into json, then we parse and send back the last item which is the uuid. return JSON.parse(atob(base64StringOrUuidd))[3]; } catch (e) { // if there is an error it's because the string is already a uuid an we can just let it through. return base64StringOrUuidd } };

@Albosonic I think you should actually be checking the last element in the decoded array, I believe it can fluctuate based on foreign key relations the object has

@jarofghosts good suggestion thanks.

Further, note that Postgraphile has an option that solves @jarvisuser90 's highlighted issue with breaking Relay's expected schema, the classicIds option [1]:

classicIds: Enables classic ids for Relay support. Instead of using the field name nodeId for globally unique ids, PostGraphile will instead use the field name id for its globally unique ids. This means that table id columns will also get renamed to rowId.

The punchline is that with that option enabled, id is the global Relay id, and rowId is the database level id.

[1] https://www.graphile.org/postgraphile/usage-schema/#api-createpostgraphileschemapgconfig-schemaname-options

@Kobold with classicIds enabled, thus using id (generated for Relay) and rowId(database) for identification, do you have any opinion on what are the best practices on the Relay client / front-end code?

For instance, should you strive to only use id (generated for Relay) and avoid using rowId (database) for querying, updates and so on? What about url states, often you want to have a selected item id in the url for state management but also for url sharing/bookmarking, will that work using id (generated for Relay), and will it look pretty?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lishine picture lishine  路  3Comments

sachaarbonel picture sachaarbonel  路  3Comments

coco98 picture coco98  路  3Comments

tirumaraiselvan picture tirumaraiselvan  路  3Comments

revskill10 picture revskill10  路  3Comments