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 data model:

The Query type of the Prisma GraphQL schema defines all the queries the Prisma API accepts.
As an example, consider the following data model:
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 data model, three queries are generated. Taking above the above User type as an example, these queries are:
user: Retrieve a singleUsernodeusers: Retrieve a list ofUsernodes (as an object query)usersConnection: Retrieve a list ofUsernodes (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:

Data model for examples on this page
All example queries on this page are based on a Prisma service configured with this data model:
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 data model, 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 data model 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
firstandbefore,lastandafter, andskip
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
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
}
}
likedPostsis not part of the above mentioned data model but can easily be added by adding the corresponding field to theUsertype:likedPosts: [Post!]! @relation(name: "LikedPosts"). We also provide anamefor the relation to resolve the ambiguity we would otherwise create because there are two relation fields targettingPoston theUsertype.
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 totrue, all of the nested conditions have to betrue. - For an
OR-filter to evaluate totrue, at least one of the nested conditions has to betrue. - For a
NOT-filter to evaluate totrue, all of the nested conditions have to befalse.
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.
Pagination
When querying all nodes of a specific object type, you can supply arguments that allow you to paginate the query response.
Seeking forward and backward with first and last
Pagination allows you to request a certain chunk of nodes. You can seek forwards or backwards through the nodes and supply an optional starting node:
- To seek forward, use
first; specify a starting node withafter. - To seek backward, use
last; specify a starting node withbefore.
You cannot combine first with before or last with after. If you do so in a query, before or after will simply be ignored and only first or last is applied (at the very beginning or end of the list, depending on which you're using).
Note that you can query for more nodes than exist without an error message.
Skipping elements with skip
You can also skip an arbitrary amount of nodes in whichever direction you are seeking by supplying the skip argument:
- When using
first,skipskips elements at the beginning of the list - When using
last,skipskips elements from the end of the list
Examples
For the following examples, we're assuming a list of exactly 30 nodes:

Query the first 3 nodes (seeking forward):

query {
posts(first: 3) {
id
title
}
}
Query the nodes from position 6 to position 10 (seeking forward):

query {
posts(first: 5, skip: 5) {
id
title
}
}
Query the last 3 nodes (seeking backward):

query {
posts(last: 3) {
id
title
}
}
Query the nodes from position 21 to position 27 (seeking backward):

query {
posts(last: 7, skip: 3) {
id
title
}
}
Query the first 3 nodes after the node with cixnen24p33lo0143bexvr52n as id:

query {
posts(first: 3, after: "cixnen24p33lo0143bexvr52n") {
id
title
}
}
Query the first 5 nodes after the node with cixnen24p33lo0143bexvr52n as id and skipping 3 nodes:

query {
posts(first: 5, after: "cixnen24p33lo0143bexvr52n", skip: 3) {
id
title
}
}
Query the last 5 nodes before the node with cixnen24p33lo0143bexvr52n as id:

query {
posts(last: 5, before: "cixnen24p33lo0143bexvr52n") {
id
title
}
}
Query the last 3 nodes before the node with cixnen24p33lo0143bexvr52n as id and skipping 5 nodes:

query {
posts(last: 3, before: "cixnen24p33lo0143bexvr52n", skip: 5) {
id
title
}
}