От одного до многих отношений с Самим собой на Призме

#mysql #typescript #prisma #prisma2

Вопрос:

Я пытаюсь реализовать простое приложение, похожее на tinder, с Prisma, в котором пользователь может проводить пальцем влево и вправо, чтобы понравиться или не понравиться другому пользователю, и после этого я должен был получить совпадения и кандидатов. Совпадения-это все пользователи, которым я тоже нравлюсь, в то время как кандидаты-это все пользователи, кроме меня, моих совпадений, пользователей, которые мне не нравятся, и пользователей, которым я не нравлюсь.

Я работал над созданием модели пользователя, модели симпатий и модели антипатий

 model User {
  id            String     @id
  username      String     @default(value: "")
  age           Int        @default(value: 0)
  bio           String     @default(value: "") @db.VarChar(1000)
}

model Likes {
  id          Int    @id @default(autoincrement())
  userId      String
  likedUserId String
}

model Dislikes {
  id             Int    @id @default(autoincrement())
  userId         String
  dislikedUserId String
}
 

и создав пару довольно сложных SQL — операторов, запустив их с queryRaw

Это действительно работает, но я чувствую, что неправильно использую Prisma, я просто перевожу SQL в Prisma. Поэтому я решил изменить свою модель следующим образом

 model User {
  id            String     @id
  username      String     @default(value: "")
  age           Int        @default(value: 0)
  bio           String     @default(value: "") @db.VarChar(1000)
  liked         User[]     @relation("LikedUserToUser")
  disliked      User[]     @relation("DislikedUserToUser")
}
 

к которому моя IDE побудила меня добавить противоположное отношение или запустить prisma format
Сделав это, я получил что-то вроде этого

 model User {
  id           String     @id
  username     String     @default(value: "")
  age          Int        @default(value: 0)
  bio          String     @default(value: "") @db.VarChar(1000)
  liked        User[]     @relation("LikedUserToUser")
  disliked     User[]     @relation("DislikedUserToUser")
  userToLike    User?      @relation("LikedUserToUser", fields: [userId], references: [id])
  userToDislike User?      @relation("DislikedUserToUser", fields: [userId], references: [id])
  userId       String?
}
 

Теперь, похоже, это работает прилично, мне может «понравиться» пользователь с

 const user = await prisma.user.update({
    where: { id: '1' },
    data: {
      liked: {
        connect: { id: '2' },
      },
    },
  })
 

и когда я запрашиваю пользователя «1», включая лайки, я получаю

 {
  id: '1',
  username: 'Cheryl',
  age: 36,
  bio: 'ornare, libero at auctor ullamcorper',
  userId: null,
  liked: [
    {
      id: '2',
      username: 'Daphne',
      age: 57,
      bio: 'at sem molestie sodales',
      userId: '1'
    }
  ]
}
 

Моя проблема в том, что я не знаю, как запускать более сложные запросы, описанные выше, совпадения и кандидатов. Есть идеи?

Ответ №1:

Ваша схема должна быть такой:

 model User {
  id             String  @id
  username       String  @default(value: "")
  age            Int     @default(value: 0)
  bio            String  @default(value: "")
  liked          User[]  @relation("likedUsers")
  disliked       User[]  @relation("dislikedUsers")
  likedUser      User?   @relation("likedUsers", fields: [likedUserId], references: [id])
  likedUserId    String?
  dislikedUser   User?   @relation("dislikedUsers", fields: [dislikedUserId], references: [id])
  dislikedUserId String? @map("userId")
}
 

Затем вы можете запускать запросы, подобные этому (пользователь 1 понравился пользователю 2):

 const user = await prisma.user.update({
    where: { id: '1' },
    data: {
      liked: {
        connect: { id: '2' },
      },
    },
})
 

Выбрать пользователей, которые понравились пользователю 1, также легко с помощью вложенных считываний:

 const user = await prisma.user.findUnique({
    where: { id: '1' },
    include: { liked: true }
})
 

Комментарии:

1. Это именно то, что я пытался сделать, но у меня получилось Error validating field 'liked' in model 'User': The relation field 'liked' on Model 'User' is missing an opposite relation field on the model 'User'. Either run 'prisma format' or add it manually. Запросы точно такие же, как у меня, и работают идеально

2. Это прекрасно работает. Имя @relation должно быть одинаковым, и тогда вы не получите эту ошибку.

3. При этом ошибка исчезает, но поведение странное: если я выполню приведенный выше запрос для пользователя 1, чтобы поставить лайк пользователю 2, пользователь 2 будет добавлен к лайкам пользователя 1, но также пользователь 1 будет добавлен к антипатиям пользователя 2!

4. В этом случае вам нужно будет добавить отдельное отношение для симпатий и антипатий. Редактирование схемы в моем ответе. Запрос останется прежним.