← Назад к вопросам
Как реализовать сортировку в Prisma?
2.3 Middle🔥 111 комментариев
#Soft Skills и рабочие процессы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как реализовать сортировку в Prisma
Prisma — это современный ORM для Node.js и TypeScript. Сортировка данных — одна из базовых операций, необходимых при работе с базой данных. Prisma предоставляет удобный и типобезопасный API для сортировки.
Базовая сортировка
Для сортировки используйте параметр orderBy в методах запросов:
// Сортировка по одному полю (возрастание)
const users = await prisma.user.findMany({
orderBy: {
name: 'asc'
}
});
// Сортировка по одному полю (убывание)
const users = await prisma.user.findMany({
orderBy: {
createdAt: 'desc'
}
});
Два основных направления:
'asc'— по возрастанию (A-Z, 0-9, старые даты)'desc'— по убыванию (Z-A, 9-0, новые даты)
Множественная сортировка
Отсортируйте по нескольким полям — порядок имеет значение:
// Сначала по категории, затем по цене
const products = await prisma.product.findMany({
orderBy: [
{ category: 'asc' },
{ price: 'desc' }
]
});
// Результат будет сначала отсортирован по категории,
// а внутри каждой категории по цене (дороже сначала)
Сортировка с фильтрацией
// Получить активных пользователей, отсортированных по дате регистрации
const users = await prisma.user.findMany({
where: {
active: true
},
orderBy: {
createdAt: 'desc'
}
});
// С лимитом (для пагинации)
const latestPosts = await prisma.post.findMany({
where: {
published: true
},
orderBy: {
publishedAt: 'desc'
},
take: 10
});
Сортировка по связанным полям
// Сортировка по имени автора (через связь)
const posts = await prisma.post.findMany({
orderBy: {
author: {
name: 'asc'
}
},
include: {
author: true
}
});
// По количеству комментариев
const posts = await prisma.post.findMany({
orderBy: {
comments: {
_count: 'desc'
}
}
});
Функции для сортировки
Prisma поддерживает специальные функции в orderBy:
// Случайная сортировка
const randomUsers = await prisma.user.findMany({
orderBy: {
_rand: 'asc'
}
});
// Длина текста (для PostgreSQL)
const posts = await prisma.post.findMany({
orderBy: {
content: {
_length: 'desc'
}
}
});
Динамическая сортировка
// Функция для построения динамического orderBy
function buildOrderBy(sortField, sortOrder) {
if (!sortField) {
return undefined;
}
const order = sortOrder === 'desc' ? 'desc' : 'asc';
return { [sortField]: order };
}
const orderBy = buildOrderBy('name', 'asc');
const users = await prisma.user.findMany({ orderBy });
// С множественной сортировкой
function buildMultipleOrderBy(sortConfig) {
return sortConfig.map(({ field, order }) => ({
[field]: order === 'desc' ? 'desc' : 'asc'
}));
}
const orderBy = buildMultipleOrderBy([
{ field: 'category', order: 'asc' },
{ field: 'price', order: 'desc' }
]);
const products = await prisma.product.findMany({ orderBy });
Пагинация со сортировкой
// Получить страницу с 10 элементами, отсортированными по дате
const page = 2;
const pageSize = 10;
const users = await prisma.user.findMany({
skip: (page - 1) * pageSize,
take: pageSize,
orderBy: {
createdAt: 'desc'
}
});
// С общим количеством
const [users, total] = await Promise.all([
prisma.user.findMany({
skip: (page - 1) * pageSize,
take: pageSize,
orderBy: {
createdAt: 'desc'
}
}),
prisma.user.count()
]);
const totalPages = Math.ceil(total / pageSize);
Сортировка с агрегацией
// Получить пользователей, отсортированных по количеству постов
const users = await prisma.user.findMany({
select: {
id: true,
name: true,
_count: {
select: { posts: true }
}
},
orderBy: {
posts: {
_count: 'desc'
}
}
});
// Результат будет содержать количество постов и отсортирован по нему
users.forEach(user => {
console.log(`${user.name}: ${user._count.posts} постов`);
});
Кейс-инсенситивная сортировка
// PostgreSQL: сортировка без учёта регистра
const users = await prisma.user.findMany({
orderBy: {
name: { sort: 'asc', nulls: 'last' }
}
});
// MySQL: используй COLLATE в сыром запросе
const users = await prisma.$queryRaw`
SELECT * FROM User
ORDER BY name COLLATE utf8mb4_general_ci ASC
`;
Обработка null значений
// PostgreSQL
const users = await prisma.user.findMany({
orderBy: {
name: { sort: 'asc', nulls: 'last' }
}
});
// MySQL (нет встроенной поддержки, обрабатывай в коде)
const users = await prisma.user.findMany({
orderBy: {
name: 'asc'
}
});
// Отсортируй вручную
users.sort((a, b) => {
if (a.name === null) return 1;
if (b.name === null) return -1;
return a.name.localeCompare(b.name);
});
Практический пример: API endpoint
// POST /api/products
async function getProducts(req, res) {
const {
page = 1,
pageSize = 20,
sortBy = 'createdAt',
sortOrder = 'desc',
search = ''
} = req.query;
const skip = (page - 1) * pageSize;
const [products, total] = await Promise.all([
prisma.product.findMany({
where: {
OR: [
{ name: { contains: search, mode: 'insensitive' } },
{ description: { contains: search, mode: 'insensitive' } }
]
},
orderBy: {
[sortBy]: sortOrder === 'desc' ? 'desc' : 'asc'
},
skip,
take: parseInt(pageSize),
include: {
category: true,
reviews: {
select: { rating: true }
}
}
}),
prisma.product.count({
where: {
OR: [
{ name: { contains: search, mode: 'insensitive' } },
{ description: { contains: search, mode: 'insensitive' } }
]
}
})
]);
res.json({
data: products,
pagination: {
page: parseInt(page),
pageSize: parseInt(pageSize),
total,
totalPages: Math.ceil(total / pageSize)
}
});
}
Рекомендации
- Всегда добавляйте индексы на поля, по которым часто сортируете
- Используйте
takeиskipдля пагинации вместе с сортировкой - Множественная сортировка полезна для сложной логики упорядочивания
- Проверяйте сортировку по связанным полям — может потребоваться дополнительный include
- В production кэшируйте результаты, если сортировка дорогая