ORM - Prisma
Первая таблица - Основные данные сущности
Вторая таблица - Дополнительные данные сущности
Отношение - Many to one
Хотя этот вопрос подходит и к варианту если таблица одна, так как смысл +- такой же, наверно, помню в доках видел что то про получение поля _count но не уверен что по нему можно сделать правильную пагинацию
Задача: нужно собирать данные из обеих таблицы с группировкой по колонкам первой и пагинируя по кол-ву (per_page) элементов группы из второй, если брать стандартный метод призмы "groupBy" то получается что я никак не могу предварительно разбить элементы связанной таблицы группы на страницы так как в параметрах группировки не могу делать выборку по связанным таблицы, в итоге наколхозил такой вариант, но предварительно скажу что он не особо оптимальный по производительности на большое кол-во групп, с этим я и пытаюсь собственно разобраться но по итогу получается закольцованная зависимость по данным, что бы получить конкретное кол-во групп нужно знать сколько у каждой группы элементов из второй таблицы, дабы не превышать лимит кол-ва, а что бы получить кол-во нужно получить сами группы
interface GroupedOutput {
keys: { date: string, field1: string, field2: string }
items: any[]
}
const prisma: any = {}
class TestModel {
public static async findGrouped({ order = 'asc', field = 'id', ...args }: FindGroupedArgs) {
const { page, limit, orderNumber, ...query } = args
const primaryWhere = this.getPrimaryFindWhere(query)
// TODO: Как вариант для оптимизации загружать по 1 группе
// И уже в цикле в конце пушить новую группу и удалять текущую в начале,
// Цикл for поменять на while проверять на то что в массиве есть элементы
const grouped = await prisma.primaryTable.groupBy({
by: ['date', 'field1', 'field2'],
where: primaryWhere, orderBy: { date: 'desc' },
})
let prev = 0
const list: GroupedOutput[] = []
for await (const keys of grouped) {
const relatedQuery = { ...keys, field2: query?.field2 }
const relatedWhere = await this.getRelatedFindWhere(relatedQuery, orderNumber)
const count = await prisma.relatedTable.count({ where: relatedWhere })
prev += count
if (this.isPrevGroupedPage(prev, limit, page)) continue
const total = list.reduce((acc, it) => acc + it.items.length, 0)
if (this.isNextGroupedPage(total, count, limit)) break
const items = await prisma.relatedTable.findMany({
where: relatedWhere,
orderBy: { id: 'desc' },
})
list.push({ keys, items })
}
const totalWhere = await this.getRelatedFindWhere(query, orderNumber)
const total = await prisma.relatedTable.count({ where: totalWhere })
return { items: list, total }
}
private static isPrevGroupedPage(prev: number, limit: number, page: number) {
return prev <= (limit * page) - limit
}
private static isNextGroupedPage(total: number, count: number, limit: number) {
return total + count > limit
}
private static getPrimaryFindWhere(query: any) {
return {}
}
private static getRelatedFindWhere(query: any, orderNumber: string) {
return {}
}
}