cocomon

Filtering and sorting

WhereInput trees, relation filters, ordering, distinct, skip/take, and cursor pagination.

Filtering and sorting

Every model gets a WhereInput, WhereUniqueInput, and OrderByInput family.

This page is about query shaping. For create/update/delete examples, continue with CRUD. For nested reads and writes, continue with Relations and includes.

Logical groups

WhereInput can combine conditions through AND, OR, and NOT.

final users = await db.user.findMany(
  where: UserWhereInput(
    AND: <UserWhereInput>[
      const UserWhereInput(name: StringFilter(contains: 'Ali')),
      const UserWhereInput(role: EnumFilter<Role>(equals: Role.member)),
    ],
  ),
);

Scalar filters

Common operator families:

  • numbers: equals, not, in, notIn, lt, lte, gt, gte
  • strings: equals, not, in, notIn, contains, startsWith, endsWith
  • dates: equals, not, lt, lte, gt, gte
  • enums: equals, not, in, notIn
  • booleans: equals, not
final posts = await db.post.findMany(
  where: const PostWhereInput(
    title: StringFilter(contains: 'docs'),
    createdAt: DateTimeFilter(gte: DateTime(2026, 3, 1)),
  ),
);

Relation filters

Use relation filters to query through related records.

final users = await db.user.findMany(
  where: UserWhereInput(
    posts: PostListRelationFilter(
      some: const PostWhereInput(
        status: EnumFilter<PostStatus>(equals: PostStatus.published),
      ),
    ),
  ),
);

Ordering

final posts = await db.post.findMany(
  orderBy: const <PostOrderByInput>[
    PostOrderByInput(createdAt: SortOrder.desc),
    PostOrderByInput(title: SortOrder.asc),
  ],
);

Distinct

Use distinct when you want unique rows by one or more fields in the generated query layer.

final posts = await db.post.findMany(
  distinct: const <PostScalarField>[PostScalarField.authorId],
);

Offset pagination

final page = await db.post.findMany(
  skip: 40,
  take: 20,
  orderBy: const <PostOrderByInput>[
    PostOrderByInput(createdAt: SortOrder.desc),
  ],
);

Cursor pagination

final page = await db.post.findMany(
  cursor: const PostWhereUniqueInput(id: 100),
  take: 20,
  orderBy: const <PostOrderByInput>[
    PostOrderByInput(id: SortOrder.asc),
  ],
);

Backward pagination uses a negative take:

final previousPage = await db.post.findMany(
  cursor: const PostWhereUniqueInput(id: 100),
  take: -20,
  orderBy: const <PostOrderByInput>[
    PostOrderByInput(id: SortOrder.asc),
  ],
);

Continue with

On this page