Агрегация отношений Prisma 3 (сумма)

#javascript #postgresql #prisma

Вопрос:

У меня возникли некоторые проблемы с получением суммы для соответствующих данных.

Это моя схема:

 model Vote {
  userId Int
  user   User @relation(fields: [userId], references: [id])
  itemId Int
  item   Item @relation(fields: [itemId], references: [id])
  value  Int

  @@id([userId, itemId])
}

model Item {
  id        Int      @id @default(autoincrement())
  userId    Int
  user      User     @relation(fields: [userId], references: [id])
  listId    Int
  list      List     @relation(fields: [listId], references: [id])
  votes     Vote[]
  body      String   @db.VarChar(255)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model List {
  id          Int      @id @default(autoincrement())
  userId      Int
  user        User     @relation(name: "Ownership", fields: [userId], references: [id])
  items       Item[]
  sharedWith  User[]   @relation(name: "Shared")
  title       String   @db.VarChar(255)
  description String?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

model User {
  id         Int      @id @default(autoincrement())
  email      String   @unique
  password   String
  name       String?
  lists      List[]   @relation(name: "Ownership")
  items      Item[]
  votes      Vote[]
  sharedWith List[]   @relation(name: "Shared")
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
}
 

То, что я пытаюсь понять, это:

  • 1 Список по идентификатору
  • Включенные элементы списка
  • И для каждого элемента сумма значений (из таблицы голосования).

Вот что я придумал:

 prisma.list.findUnique({
    where: { id },
    include: {
        items: {
            include: {
                votes: {
                    include: {
                        _sum: {
                            select: {
                                value: true,
                            },
                        },
                    },
                },
            },
        },
    },
})
 

Я построил запрос на основе нескольких различных запросов, которые я нашел в Интернете (большинство из них в документах Prisam).

Также я заметил, что в документах Prisma отсутствует много вещей, таких как (добавление/удаление связанных данных — многие ко многим отношениям). Есть ли какие-нибудь лучшие документы или пример проекта с подобными материалами?

Спасибо!

Ответ №1:

В настоящее время это невозможно выполнить в виде одного запроса. Что вы можете сделать, так это суммировать значения после того, как получите их обратно.

Я создал аналогичный пример на основе StackOverflow. Учитывая следующую схему Призмы:

 // This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id        Int        @id @default(autoincrement())
  name      String
  votes     Vote[]
  questions Question[]
}

model Question {
  id       Int    @id @default(autoincrement())
  question String
  votes    Vote[]
  user     User   @relation(fields: [userId], references: [id])
  userId   Int
}

model Vote {
  id         Int      @id @default(autoincrement())
  value      Int      @default(1)
  questionId Int
  question   Question @relation(fields: [questionId], references: [id])
  user       User     @relation(fields: [userId], references: [id])
  userId     Int
}
 

Вы можете написать следующий сценарий:

 import { PrismaClient } from "@prisma/client"
const prisma = new PrismaClient()

async function main() {
  const users = await prisma.user.findMany({
    include: {
      questions: {
        include: {
          votes: {
            select: {
              value: true,
            },
          },
        },
      },
    },
  })

  for (let user of users) {
    for (let question of user.questions) {
      let vote_sum = 0
      for (let vote of question.votes) {
        vote_sum  = vote.value
      }
      ;(question as any).vote_sum = vote_sum
    }
  }

  console.dir(users, { depth: Infinity })
}

main().catch((err) => console.error(err))
 

Затем суммируйте значения после получения данных обратно.

Если это вам не подходит, я бы посоветовал вам написать запрос на функцию для команды Prisma.