Search code examples
databasepostgresqlgraphqlmutationpostgraphile

Update a column value in a Postgres table using Graphql mutation


Basic info: using Postgres in the backend and GraphQL in the front end using Postgraphile.

Need: Use a GraphQL mutation to update a row in the Postgres DB.

Code: Suppose I have a library_account schema which has book table in Postgres which has fields like id, title, borrower_id and is_available.

Scenario: It is getting borrowed for the very first time.

Proposed flow: make a GraphQL mutation to update the Postgres table with the borrower_id.

Code I am currently using:

mutation BookUpdates(
  $title: String,
  $borrower_id: Int!, #not really an Int but for the sake of ease.
  $author_id: Int!,
  $isle_id: Int!,
  $is_available: Boolean
) {
  updateBookByAuthorIdAndIsleId(input: {
    isle_id: $isle_id,
    is_available: $is_available,
    borrower_id: $borrower_id,
    author_id: $author_id
}) {
  bookEdge {
    node {
      author_id
    }
  }
}

Here, I am getting an error for borrower_id which says that borrower_id is not defined by type updateBookByAuthorIdAndIsleId.

Any suggestions??


Solution

  • When constructing queries and mutations in GraphQL it's often wise to use a client such as GraphiQL which will help you by providing the documentation, giving you auto-complete capabilities, and highlighting where errors have occurred. PostGraphile has GraphiQL built in; it's enabled by default on the CLI but if you're using it in library mode you must pass graphiql: true to enable it. Either way I recommend you use the --enhance-graphiql / enhanceGraphiql: true flags. If you take your mutation and put it into GraphiQL it should tell you where it went wrong, and may even suggest how to fix it!

    It looks to me like your mutation is slightly the wrong shape. PostGraphile follows the Relay Input Object Mutations Specification, which means we nest all of the mutation inputs under the input argument, as you have done. However, we also group together the details about the record so that it's easier to separate the "what" from the "how" when doing updates - e.g. "what": authorId: 27, isleId: 93, "how": patch: {text: $text} - this also allows you to update the keys (e.g. if you wanted to change the isleId) which wouldn't be possible if all the columns were in together. This is the part you're missing, I believe.

    I suspect that your mutation should look more like:

    mutation BookUpdates(
      $borrower_id: Int!, #not really an Int but for the sake of ease.
      $author_id: Int!,
      $isle_id: Int!,
      $is_available: Boolean
    ) {
      updateBookByAuthorIdAndIsleId(input: {
        isleId: $isle_id,
        authorId: $author_id
        bookPatch: {
          isAvailable: $is_available,
          borrowerId: $borrower_id,
        }
    }) {
      bookEdge {
        node {
          authorId
        }
      }
    }
    

    I've also camelCase'd your field names, but if you've loaded a custom inflector this might not be necessary/desirable.