← Назад к вопросам

Как реализовать сортировку в 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 кэшируйте результаты, если сортировка дорогая