@awenn2015
Веб-программист самоучка

Как сгрупировать данные с корректной пагинацией по кол-ву элементов из связанной таблицы?

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 {}
  }
}
  • Вопрос задан
  • 70 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы