HoudiniGraphql / houdini

The disappearing GraphQL framework
http://www.houdinigraphql.com
MIT License
913 stars 99 forks source link

Improve List Handling for Direct Message Queries Without Needing @parentID #1367

Closed banakh closed 1 month ago

banakh commented 1 month ago

Describe the feature

Description:

Currently, in HoudiniGraphQL, when working with a list of messages tied to a specific parent entity (like tickets), we have to manually pass the @parentID in mutations when inserting new records. This can result in unnecessary complexity and redundant joins, especially when the parent-child relationship is straightforward.

For example, when fetching ticket messages in our application, we currently have the following setup: Current Query:

query getAllTicketMessages($taskId: Int!) {
  allDocumentTemplateTickets(condition: { documentTemplateTicketId: $taskId }) {
    nodes {
      id
      documentTemplateTicketMessagesByDocumentTemplateTicketId @list(name: "ticket_messages") {
        nodes {
          id
          message
        }
      }
    }
  }
}

Current Mutation:

const createMessageMutation = graphql(`
  mutation CreateTicketMessage($documentTemplateTicketId: Int!, $message: String) {
    createDocumentTemplateTicketMessage(
      input: {
        documentTemplateTicketMessage: {
          documentTemplateTicketId: $documentTemplateTicketId
          message: $message
        }
      }
    ) {
      documentTemplateTicketMessage {
        ...ticket_messages_insert @parentID(value: $documentTemplateTicketId)
      }
    }
  }
`);

Proposed Improvement:

The proposal is to allow querying the messages directly, without needing to go through the parent ticket entity. This simplifies both the query and the mutation by eliminating the need for manually specifying @parentID.

Proposed Query:

query getAllTicketMessages($taskId: Int!) {
  allDocumentTemplateTicketMessages(condition: { documentTemplateTicketId: $taskId }) {
    nodes @list(name: "ticket_messages", parentID: "documentTemplateTicketId") {
      id
      message
      documentTemplateTicketId
    }
  }
}

This allows fetching the messages directly using the documentTemplateTicketId without having to reverse the relationship to the ticket itself.

Proposed Mutation:

const createMessageMutation = graphql(`
  mutation CreateTicketMessage($documentTemplateTicketId: Int!, $message: String) {
    createDocumentTemplateTicketMessage(
      input: {
        documentTemplateTicketMessage: {
          documentTemplateTicketId: $documentTemplateTicketId
          message: $message
        }
      }
    ) {
      documentTemplateTicketMessage {
        ...ticket_messages_insert
      }
    }
  }
`);

Benefits:

  1. Simpler Queries: The query becomes more efficient since we directly fetch the relevant messages using their documentTemplateTicketId, avoiding unnecessary joins.
  2. No More @parentID in Mutations: By making the list automatically aware of its parentID, we remove the need to pass it in the mutation, reducing boilerplate and simplifying mutation logic.
  3. Better Performance: Fewer joins mean lighter queries and faster response times when dealing with large datasets.

Conclusion:

By implementing this improvement, HoudiniGraphQL will be able to handle lists more intuitively, reducing the need for manual @parentID specification in scenarios where it's unnecessary. This will improve both developer experience and performance.

Criticality

nice to have

AlecAivazis commented 1 month ago

Thanks for reporting this! I think #1130 is a slightly more elegant approach as it addresses the core issue directly. It feels a bit strange to me to have an arbitrary argument act as a label for a list instead of just having a way to embed that label in the actual object returning the list

AlecAivazis commented 1 month ago

I'm closing this in favor of #1130

1mehal commented 1 month ago

@AlecAivazis from our experience (having a non controlled GraphQL environment) it's hard to add __id field, but definitely being able to specify custom id fields works better for us