CRUD Operations
findUnique
Get a single record by unique identifier
Retrieve a single record by its primary key or unique field.
// By primary key
const user = await client.user.findUnique({
where: { id: "user-123" },
});
// By unique field
const user = await client.user.findUnique({
where: { email: "alice@example.com" },
});Return Type
Returns the record or null if not found:
const user: User | null = await client.user.findUnique({
where: { id: userId },
});
if (user === null) {
// Record doesn't exist
}For error handling, use findUniqueOrThrow.
By Primary Key
Use the @id field:
const user = await client.user.findUnique({
where: { id: "123" },
});
const todo = await client.todo.findUnique({
where: { id: "456" },
});By Unique Field
Use any field marked with @unique:
const user = await client.user.findUnique({
where: { email: "alice@example.com" },
});Your Prisma schema determines which fields support unique lookup:
model User {
id String @id
email String @unique // Can use in findUnique
name String
}Composite Unique Keys
For models with @@unique on multiple fields:
model Post {
id String @id
slug String
boardId String
@@unique([slug, boardId]) // Composite unique constraint
}Query using both fields:
const post = await client.post.findUnique({
where: {
slug_boardId: {
// Composite key name
slug: "hello-world",
boardId: "board-123",
},
},
});Selection
Control which fields are returned:
const user = await client.user.findUnique({
where: { id: userId },
select: { id: true, name: true, email: true },
});Relations
Include related records:
const user = await client.user.findUnique({
where: { id: userId },
include: { profile: true },
});
const userWithTodos = await client.user.findUnique({
where: { id: userId },
include: {
profile: true,
todos: {
where: { done: false },
orderBy: { createdAt: "desc" },
},
},
});Performance
findUnique performs a direct indexed lookup, typically O(log n) in typical B-tree/index implementations:
// ✅ Faster - direct indexed lookup
const user = await client.user.findUnique({
where: { id: userId }, // Logarithmic via index
});
// ⚠️ May be slower if fields are not indexed
const user = await client.user.findFirst({
where: { email: "alice@example.com" },
}); // Can be fast with appropriate indexesEnsure your lookup fields are indexed in your schema for best performance.
Null Handling
const user = await client.user.findUnique({
where: { id: userId },
});
// Type-safe null check
if (user === null) {
console.log("User not found");
} else {
console.log(user.name);
}
// Optional chaining
console.log(user?.name);Use Cases
User Session
const currentUser = await client.user.findUnique({
where: { id: sessionUserId },
});
if (!currentUser) {
redirectToLogin();
}Resource Access
const todo = await client.todo.findUnique({
where: { id: todoId },
});
if (!todo) {
throw new Error("Todo not found");
}
// Verify ownership
if (todo.userId !== currentUserId) {
throw new Error("Access denied");
}See Also
- findUniqueOrThrow - Throws if not found
- findFirst - Get first matching record
- findMany - Get multiple records