1

In my app every customer has a own table for its data. Depending on which customer was selected I want to dynamically build the tablename for the Graphql query.

For example:

// Query for customer 1
gql`
  query overviewQuery {
    customer_1 {
      aggregate {
        count
      }
  }
}
`
// Query for customer 2
gql`
  query overviewQuery {
    customer_2 {
      aggregate {
        count
      }
  }
}
`

I have the customer id in my vuex store and want to insert a variable into the query like in the following pseudocode which is not working.

const tblUserAggregateName = `customer_${this.$store.state.customer.customerId`

gql`
  query overviewQuery {
    ${this.tblUserAggregateName} {
      aggregate {
        count
      }
  }
`

Is there an option how to do this or how can this problem be solved?

It is not an option to hardcode all different customer queries and selected them on runtime.

Thanks!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Thomas K.
  • 121
  • 1
  • 10

2 Answers2

3

In the answers it was mentioned, that it is against best practice to dynamically change the table name of GraphQL queries.

As changing the complete database structure for all clients (they each have a separate Database with a own PostgreSQL schema name) is not an option, I found a solution the looks a little bit hacky and definitely not best practice but I thought I might be interesting to share for others with the same problem.

The approach is pretty easy: I write the query as a simple string where I could use variables and convert them later to the gql AST Object with graphql-tag

const query = () => {
  const queryString = `
    {
      ${customerId}_table_name {
        aggregate {
           count
        }
      }
  }`

  return gql`${queryString}`
}

Works, but I you have a better solution, I am happy to learn!

Thomas K.
  • 121
  • 1
  • 10
0

You can supply variables, but they should not be used to dynamically infer schema object names. This violates core concepts of GraphQL. Try this instead:

gql`
  query overviewQuery ($customerId: ID!) {
    customerData (id: $customerId) {
      tableName
      aggregate {
        count
      }
    }
  }`

Apollo provides great documentation on how to supply variables into a query here: https://www.apollographql.com/docs/react/data/queries/

The backend can then use the customerId to determine what table to query. The client making requests does not need to know (nor should it) where that data is or how it's stored. If the client must know the table name, you can add a field (as shown in the example)

Bemis
  • 3,092
  • 2
  • 17
  • 24
  • Thank you for the explanation. So when using graphql I automatically have to use a database design where multiple tenants share the same table / database and are identified with an columnId? – Thomas K. Feb 04 '22 at 09:12
  • GraphQL is just another approach to API (akin to REST or gRPC). It's just the glue to connect clients to the backend offering some advantages over REST/gRPC (comparison here: https://medium.com/devops-dudes/graphql-vs-rest-vs-grpc-411a0a60d18d). You can still store your tenant data separately in the backend and use the id's to generate the table names and return the appropriate data. – Bemis Feb 04 '22 at 16:44