How to combine a mutation and a query in a single query?
Asked Answered
G

3

18

I have an operation getFoo that requires that the user is authenticated in order to access the resource.

User authenticates using a mutation authenticate, e.g.

mutation {
  authenticate (email: "foo", password: "bar") {
    id
  }
}

When user is authenticated, two things happen:

  1. The request context is enriched with the authentication details
  2. A cookie is created

However, I would like to combine authentication and getFoo method invocation into a single request, e.g.

mutation {
  authenticate (email: "foo", password: "bar") {
    id
  }
}
query  {
  getFoo {
    id
  }
}

The latter produces a syntax error.

Is there a way to combine a mutation with a query?

Gonagle answered 12/10, 2017 at 20:51 Comment(1)
Was it somehow related with CQS / CQRS and have you found your answer?Oviposit
I
17

There's no way to send a mutation and a query in one request according to the GraphQL specification.

However, you can add any fields to the mutation payload. So if there are only a handful of queries that you need to support for the authenticate mutation, you could to this, for example:

mutation {
  authenticate (email: "foo", password: "bar") {
    id
    getFoo {
      id
    }
  }
}

At the end of the day, it might be better to keep the mutation and query separate though. It gets hairy very quickly if you want to include many queries in many mutations like this. I don't see a problem with the overhead of an additional request here.

Ibnrushd answered 12/10, 2017 at 21:21 Comment(2)
can you paste the link for grpahql spec on this?Slobber
graphql will help reduce the number of calls they said!! now client has to send mutation and query separately!!Tubulate
V
1

This is not possible without support by the server. However:

  • Some GraphQL APIs support batching of operations where you can send an array of queries and/or mutations in a single request.

  • Other APIs support HTTP2+, where you can easily send multiple requests on the same connection without any overhead.

  • If you control the API, you can also apply a little trick where you simply expose the getFoo field not just on the Query type but also on the Mutation type. There is not that much of a difference, except that mutation { … } fields are resolved sequentially. You can go even further and expose the whole Query type on mutations, allowing you to query arbitrary data and not just start querying the graph at the mutation result. It would look like this:

    type Mutation {
      query: Query!
      … # authenticate() etc
    }
    
    mutation authAndFoo {
      authenticate (email: "foo", password: "bar") {
        id
      }
      query {
        getFoo {
          id
        }
      }
    }
    
Vastha answered 24/7, 2022 at 18:47 Comment(0)
M
0

I found your post yesterday because I had the same question as you. I would like to contribute answering that what you want to do is quite possible using fragments. Here is the source: https://www.apollographql.com/docs/react/data/fragments/

Here's a quick explanation:

  • define your data fragment
export const FRAGMENT_USER = gql`
    fragment UserDataFragment on User {
        uuid
    }
`;
  • add the defined fragments to your InMemoryCache:
cache: new InMemoryCache({
    fragments: createFragmentRegistry(gql`
        ${FRAGMENT_USER}
    `),
}),
  • define your graphql queries using the fragment:
export const GET_ME = gql`
    query Me {
        me {
            ...UserDataFragment
        }
    }
`;

export const DO_LOGIN = gql`
    mutation Login($email: String!, $password: String!) {
        login(email: $email, password: $password) {
            ... on User {
                ...UserDataFragment
            }
        }
    }
`;

When you call your mutation, it will return the fragment data you declared. No need to perform another request.

Note: fragments are defined client-side.

Mesarch answered 8/3 at 21:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.