API

GraphQL

Graph Query language. Fixes the under-fetching and over-fetching problem.

NOT a database

GraphQL is not a database. Rather, it’s a query language that is data-agnostic.

Why not just use MySQL? And how to integrate it with a database?

GraphQL is designed in a way that allows you to write clean code on the server, where every field on every type has a focused single-purpose function for resolving that value.

Resources

Tip

Every GraphQL service defines a set of types which completely describe the set of possible data you can query on that service. Then, when queries come in, they are validated and executed against that schema.

In GraphQL (and specifically Absinthe in Elixir), the schema is a blueprint or contract that defines:

  1. The data types (like Post, User, etc.).
  2. The queries (like posts, users) that clients can perform to retrieve data.
  3. Mutations (like createPost, updateUser) for changing data.
  4. The relationships between types (e.g., how a Post relates to a User).
  5. The arguments that queries or mutations can accept (e.g., filtering or pagination arguments).

GraphQL comes with a set of default scalar types out of the box: (source)

  • Int: A signed 32‐bit integer
  • Float: A signed double-precision floating-point value
  • String: A UTF‐8 character sequence
  • Booleantrue or false
  • ID: The ID scalar type represents a unique identifier, often used to refetch an object or as the key for a cache. The ID type is serialized in the same way as a String; however, defining it as an ID signifies that it is not intended to be human‐readable.

Query

{
  human(id: "1000") {
    name
    height(unit: FOOT)
  }
}

Object Types

The most basic components of a GraphQL schema are object types, which just represent a kind of object you can fetch from your service, and what fields it has.

type Character {
  name: String!
  appearsIn: [Episode!]!
}
  • String! means that the field is non-nullable

Every field on a GraphQL object can have zero or more arguments.

type Starship {
  id: ID!
  name: String!
  length(unit: LengthUnit = METER): Float
}
  • how are these arguments passed and used?
  • and there are aliases if I remember correctly

Schemas and mutation types

Most types in your schema will just be normal object types, but there are two special schemas:

  1. query
  2. mutation

These are special because they define the entry point of every GraphQL query.

schema {
  query: Query
  mutation: Mutation
}
query {
  hero {
    name
  }
  droid(id: "2000") {
    name
  }
}

We need to define the Query rtpe.

type Query {
  hero(episode: Episode): Character
  droid(id: ID!): Droid
}

Interfaces

An Interface is an abstract type that includes a certain set of fields that a type must include to implement the interface.

For example, you could have an interface Character that represents any character in the Star Wars trilogy:

interface Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
}
type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  starships: [Starship]
  totalCredits: Int
}

But why...

Interfaces are useful when you want to return an object or set of objects, but those might be of several different types.

Reusability: When multiple types share common fields (like Character in your Star Wars example), you don’t want to repeat those fields across different type definitions.

Input Types

 input types look exactly the same as regular object types, but with the keyword input instead of type:

input ReviewInput {
  stars: Int!
  commentary: String
}

Inputs are used for passing data into mutations. Unlike object types, input types are designed specifically for input purposes (e.g., creating, updating, or deleting data). They define what shape of data is expected when clients want to modify the data on the server.

Full use case

input ReviewInput {
  stars: Int!
  commentary: String
}

Defining the Mutation:

type Mutation {
  submitReview(input: ReviewInput!): Review
}

Executing the Mutation (from the client):

mutation {
  submitReview(input: { stars: 5, commentary: "Great product!" }) {
    stars
    commentary
  }
}

Execution

Resolvers

https://www.reddit.com/r/graphql/comments/rffr95/i_dont_understand_how_graphql_can_be_performant/

Misc

Why GraphQL?

Well REST doesn’t scale really well. You need to set up different endpoints. Else it will just send you a huge chunk of data. Hmm is this true? Yes if you do a GET request. But like with a POST request, you can receive data afterwards based on the fields you request.

  • I guess the argument is POST was not designed for that principle.
  • Actually, GET requests can also include query parameters to specify fields, reducing overfetching by requesting only necessary data.

But it seems GraphQL is more configurable.

GraphQL services typically respond using JSON, however the GraphQL spec does not require it.