Prisma GraphQL APIReference

Queries

Overview

How are queries in the Prisma API generated?

The GraphQL API of a Prisma service is specified in the Prisma GraphQL schema. The Prisma GraphQL schema is auto-generated based on the service's datamodel:

The Query type of the Prisma GraphQL schema defines all the queries the Prisma API accepts.

As an example, consider the following datamodel:

type User {
  id: ID! @unique
  name: String!
}

This is the Query type Prisma will generate:

type Query {
  users(
    where: UserWhereInput
    orderBy: UserOrderByInput
    skip: Int
    after: String
    before: String
    first: Int
    last: Int
  ): [User]!
  user(where: UserWhereUniqueInput!): User
  usersConnection(
    where: UserWhereInput
    orderBy: UserOrderByInput
    skip: Int
    after: String
    before: String
    first: Int
    last: Int
  ): UserConnection!
}

For every type in your datamodel, three queries are generated. Taking above the above User type as an example, these queries are:

  • user: Retrieve a single User node
  • users: Retrieve a list of User nodes (as an object query)
  • usersConnection: Retrieve a list of User nodes (as a connection query)

To inspect all the available operations of your Prisma API in detail, you can read the Prisma GraphQL schema of your Prisma service. It can be downloaded with the GraphQL CLI:

graphql get-schema --endpoint __YOUR_PRISMA_ENDPOINT__ --output prisma.graphql --no-all

Another way to learn about the concrete capabilities of your Prisma API is by exploring the auto-generated API documentation inside a GraphQL Playground. You can do so by clicking the green SCHEMA-button at the right edge of the Playground:

Datamodel for examples on this page

All example queries on this page are based on a Prisma service configured with this datamodel:

type Post {
  id: ID! @unique
  title: String!
  published: Boolean!
  author: User!
}

type User {
  id: ID! @unique
  age: Int
  email: String! @unique
  name: String!
  accessRole: AccessRole
  posts: [Post!]!
}

enum AccessRole {
  USER
  ADMIN
}

Query concepts

The Prisma API offers two kinds of queries:

  • Object queries: Fetch single or multiple nodes of a certain object type.
  • Connection queries: Expose advanced features like aggregations and Relay compliant connections enabling a powerful pagination model.

When working with the Prisma API, the following concepts are also useful to keep in mind:

  • Hierarchical (or nested) queries: Fetch data across relations.
  • Query arguments: Allow for filtering, sorting, pagination and more.

Object queries

We can use object queries to fetch either a single node, or a list of nodes for a certain object type.

Here, we use the posts query to fetch a list of Post nodes. In the response, we include only the id and title of each Post node:

query {
  posts {
    id
    title
  }
}

We can also query a specific Post node using the post query. Note that we're using the where argument to select the node:

query {
  post(where: { id: "cixnen24p33lo0143bexvr52n" }) {
    id
    title
    published
  }
}

Because User is another type in our datamodel, users is another available query. Again, we can use the where argument to specify conditions for the returned users. In this example, we filter for all User nodes that have their age higher than 18:

query {
  users(where: { age_gt: 18 }) {
    id
    name
  }
}

This also works across relations. Here we're fetching those Post nodes that have an author with the age higher than 18:

query {
  posts(where: { author: { age_gt: 18 } }) {
    id
    title
    author {
      name
      age
    }
  }
}

You can read more about node selection here.

Connection queries

Object queries directly return a list of nodes. In special cases, or when using advanced features, using connection queries is the preferred option. They are an extension of (and fully compliant with) Relay connections.

The core idea of Relay connections is to provide meta-information about the edges in the data graph. For example, each edge not only has access to information about the corresponding object (the node) but also is associated with a cursor that allows to implement powerful, cursor-based pagination.

Here, we fetch all Post nodes using the postsConnection query. Notice that we're also asking for the cursor of each edge:

# Fetch all posts
query {
  postsConnection {
    edges {
      cursor
      node {
        id
        title
      }
    }
  }
}

Connection queries also expose aggregation features via the aggregate field:

# Count all posts with a title containing 'GraphQL'
query {
  postsConnection(where: { title_contains: "GraphQL" }) {
    aggregate {
      count
    }
  }
}

More aggregations will be added over time. Find more information about the roadmap here.

Querying data across relations

Every available relation in your datamodel adds a new field to the queries of the two models it connects.

Here, we are fetching a specific User node, and all its related Post nodes using the posts field:

query {
  user(where: { id: "cixnekqnu2ify0134ekw4pox8" }) {
    id
    name
    posts {
      id
      published
    }
  }
}

user.posts acts exactly like the top-level posts query in that it lets you specify which fields of the Post type you're interested in.

Query arguments

Throughout the Prisma API, you'll find query arguments that you can provide to further control the query response. It can be either of the following:

  • Ordering: Sorting nodes by any field value using orderBy
  • Filtering: Selecting nodes in a query by scalar or relational filters using where
  • Pagination: Slicing nodes in a query using first and before, last and after, and skip

These query arguments can be combined to achieve very specific query responses.

Ordering

When querying all nodes of a type you can supply the orderBy argument for every scalar field of the type: orderBy: <field>_ASC or orderBy: <field>_DESC.

Order the list of all Post nodes ascending by title:

query {
  posts(orderBy: title_ASC) {
    id
    title
    published
  }
}

Order the list of all Post nodes descending by published:

query {
  posts(orderBy: published_DESC) {
    id
    title
    published
  }
}

The field you are ordering by does not have to be selected in the actual query. If you do not specify an ordering, the response is automatically ordered ascending by the id field.

It's currently not possible to order responses by multiple fields or by related fields. Join the discussion in the feature requests if you're interested in these features!

Filtering

When querying all nodes of a type you can supply different parameters to the where argument to constrain the data in the response according to your requirements. The available options depend on the scalar and relational fields defined on the type in question.

Applying single filters

If you supply exactly one parameter to the where argument, the query response will only contain nodes that adhere to this constraint. Multiple filters can be combined using AND and/or OR, see below for more.

Filtering by a concrete value

The easiest way to filter a query response is by supplying a concrete value for a certain field to filter by.

Query all Post nodes that are not yet published:

query {
  posts(where: { published: false }) {
    id
    title
    published
  }
}

Query all User nodes with a specific name:

query {
  users(where: { name: "Alice" }) {
    id
  }
}

Query all User nodes with a specific age:

query {
  users(where: { age: 30 }) {
    id
  }
}
Advanced filter criteria

Depending on the type of the field you want to filter by, you have access to different advanced criteria you can use to filter your query response.

Query all Post nodes whose title is in a given list of strings:

query {
  posts(where: { title_in: ["My biggest Adventure", "My latest Hobbies"] }) {
    id
    title
    published
  }
}

Query all User nodes whose age is less than 42:

query {
  users(where: { age_lt: 42 }) {
    id
  }
}

Relation filters

The relation filter API when using the MongoDB database connector is constrained. You can view the Prisma GraphQL schema of your Prisma API to learn about the available filter criteria.

For to-one relations, you can define conditions on the related node by nesting the according argument in where.

Query all Post nodes where the author has the USER access role:

query {
  posts(where: { author: { accessRole: USER } }) {
    title
  }
}

For to-many relations, three additional arguments are available: every, some and none, to define that a condition should match every, some or none related nodes.

Query all User nodes that have at least one Post node that's published:

query {
  users(where: { posts_some: { published: true } }) {
    id
    posts {
      published
    }
  }
}

Relation filters are also available in the nested arguments for to-one or to-many relations.

Query all User nodes that did not like a Post of an author in the ADMIN access role:

query {
  users(where: { likedPosts_none: { author: { accessRole: ADMIN } } }) {
    name
  }
}

likedPosts is not part of the above mentioned datamodel but can easily be added by adding the corresponding field to the User type: likedPosts: [Post!]! @relation(name: "LikedPosts"). We also provide a name for the relation to resolve the ambiguity we would otherwise create because there are two relation fields targetting Post on the User type.

Combining multiple filters

You can use the filter combinators OR, AND and NOT to create an arbitrary logical combination of filter conditions:

  • For an AND-filter to evaluate to true, all of the nested conditions have to be true.
  • For an OR-filter to evaluate to true, at least one of the nested conditions has to be true.
  • For a NOT-filter to evaluate to true, all of the nested conditions have to be false.
Using OR, AND and NOT

Let's start with an easy example:

Query all Post nodes that are published and whose title is in a given list of strings:

query {
  posts(
    where: {
      AND: [
        { title_in: ["My biggest Adventure", "My latest Hobbies"] }
        { published: true }
      ]
    }
  ) {
    id
    title
    published
  }
}

OR, AND and NOT each accept a list as input where each list item is an object and therefore needs to be wrapped with curly braces. The sample filter condition from the above query contains two filter objects:

  • {title_in: ["My biggest Adventure", "My latest Hobbies"]}
  • {published: true}

Only if both filter conditions are true for a Post node, that node will be included in the response.

Arbitrary combination of filters with AND, OR and NOT

You can combine and even nest the filter combinators AND, OR and NOT to create arbitrary logical combinations of filter conditions.

Query all Post nodes that are either published and whose title is in a list of given strings, or have the specific id we supply:

query {
  posts(
    where: {
      OR: [
        {
          AND: [
            { title_in: ["My biggest Adventure", "My latest Hobbies"] }
            { published: true }
          ]
        }
        { id: "cixnen24p33lo0143bexvr52n" }
      ]
    }
  ) {
    id
    title
    published
  }
}

Notice how we nest the AND combinator inside the OR combinator.

Limitations

Currently, neither scalar list filters nor JSON filters are available. Join the discussion in the respective feature requests on GitHub.