Cerial
Queries

findUnique

Find a record by a unique field — id or any @unique-decorated field — with select and include support.

Finds a record by a unique field — either the id or any field decorated with @unique in your schema. Returns the record or null if no match exists.

The where clause must contain exactly one unique field.

const user = await client.db.User.findUnique({
  where: { id: '123' },
});
// user: User | null

Options

OptionTypeRequiredDescription
whereUserUniqueWhereInputYesMust contain exactly one unique field
selectUserSelectNoNarrow which fields are returned
includeUserIncludeNoInclude related records

Find by ID

Every model has an id field that is inherently unique:

const user = await client.db.User.findUnique({
  where: { id: '123' },
});
// user: User | null

Find by @unique Field

Any field decorated with @unique in your schema can be used:

model User {
  id Record @id
  email Email @unique
  name String
}
const user = await client.db.User.findUnique({
  where: { email: 'john@example.com' },
});
// user: User | null

Find by Object @unique Field

When an embedded object type has a field marked with @unique, you can use nested syntax to look it up:

object LocationInfo {
  address String
  zip String @unique
}

model Store {
  id Record @id
  name String
  location LocationInfo
  warehouse LocationInfo?
}
// Find by object @unique field (nested syntax)
const store = await client.db.Store.findUnique({
  where: { location: { zip: '10001' } },
});

// Each embedding is independent
const byWarehouse = await client.db.Store.findUnique({
  where: { warehouse: { zip: '90210' } },
});

With Select

const user = await client.db.User.findUnique({
  where: { id: '123' },
  select: { id: true, name: true },
});
// user: { id: CerialId; name: string } | null

With Include

const user = await client.db.User.findUnique({
  where: { email: 'john@example.com' },
  include: { profile: true },
});
// user: (User & { profile: Profile }) | null

With Select and Include

const user = await client.db.User.findUnique({
  where: { id: '123' },
  select: { id: true, email: true },
  include: { posts: true },
});
// user: ({ id: CerialId; email: string } & { posts: Post[] }) | null

findUnique vs findOne

Both methods return a single record or null, but they serve different purposes:

findUniquefindOne
Where clauseMust target a unique field (id or @unique)Any filter conditions
Use caseLook up a specific record by identifierFind first match from potentially many
OrderByNot available (result is deterministic)Supported — controls which record is returned
Type safetywhere only accepts unique fieldswhere accepts any filterable fields
Required whereYes — where is mandatoryNo — where is optional
// findUnique — when you know the exact identifier
const user = await client.db.User.findUnique({
  where: { email: 'john@example.com' },
});

// findOne — when you want the first match
const latestAdmin = await client.db.User.findOne({
  where: { role: 'admin' },
  orderBy: { createdAt: 'desc' },
});

Prefer findUnique when looking up records by id or @unique fields. The type system enforces that only unique fields are accepted, making your intent clear and preventing accidental non-unique lookups.

Return Value

  • Returns the matching record with the appropriate type based on select and include options.
  • Returns null if no record with the given unique field value exists.
ScenarioReturn
Match found, no select/includeUser | null
Match found, with select{ ...selected fields } | null
Match found, with include(User & { ...relations }) | null
No matchnull

On this page