Prisma Datamodel: первичный ключ как комбинация двух реляционных моделей - PullRequest
0 голосов
/ 19 ноября 2018

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

Должны ли Customer и Product быть объединены в первичный ключ в модели ProductReview, или это ограничениенавязываться на уровне сервера приложений, а не на уровне базы данных?

На данный момент Datamodel (неограниченная версия):

type Product {
  id: ID! @unique
  title: String!
  reviews: [ProductReview!]! @relation(name: "ProductReviews", onDelete: CASCADE)
}

type Customer {
  id: ID! @unique
  email: String @unique
}

type ProductReview {
  id: ID! @unique
  forProduct: Product! @relation(name: "ProductReviews", onDelete: SET_NULL)
  byCustomer: Customer!
  review: String!
  ratinng: Float!
}

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

Я должен ограничиться тем, что пользователь может отправить только один отзыв на продукт.У меня есть следующий дизайн для неограниченной ситуации.

К сожалению, в настоящее время это невозможно с Prisma.Уже существует запрос открытой функции , запрашивающий эту функцию, пожалуйста, оставьте свой ? в вопросе!

Чтобы получить эту функцию в своем приложении, вам нужно будет включить это ограничение вручную наприкладной уровень (например, express, apollo-server или graphql-yoga).

Вы можете взглянуть на эту страницу как в GraphQL, где есть аналогичная ситуация с User, Link и Vote типы.Вот как решатель для создания Vote и не получает голосов от того пользователя, который уже существует, реализован с помощью Graphql-Yoga:

async function vote(parent, args, context, info) {
  // 1
  const userId = getUserId(context)

  // 2
  const linkExists = await context.db.exists.Vote({
    user: { id: userId },
    link: { id: args.linkId },
  })
  if (linkExists) {
    throw new Error(`Already voted for link: ${args.linkId}`)
  }

  // 3
  return context.db.mutation.createVote(
    {
      data: {
        user: { connect: { id: userId } },
        link: { connect: { id: args.linkId } },
      },
    },
    info,
  )
}
0 голосов
/ 11 июля 2019

Есть обходной путь. Для реализации концепции нескольких первичных ключей, таких как SQL. Идея проста: создайте еще одно поле с именем «UniqueCustomerReview» в разделе «ProductReview». И в то время как на мутации установите значение «UniqueCustomerReview» в «[customerEmail] _ [productID]». Так что теперь мы можем использовать уникальные по умолчанию призмы.

Ваша модель данных будет выглядеть так:

type Product {
id: ID! @unique
  title: String!
  reviews: [ProductReview!]! @relation(name: "ProductReviews", onDelete: CASCADE)
}

type Customer {
  id: ID! @unique
  email: String @unique
}

type ProductReview {
  id: ID! @unique
  forProduct: Product! @relation(name: "ProductReviews", onDelete: SET_NULL)
  byCustomer: Customer!
  review: String!
  ratinng: Float!
  UniqueCustomerReview:String!  # adding a extra field
}

Создание или запрос мутации:

mutation{
createProductReview(
data:{
forProduct: {"connect":{"id":"<Replacec_with_product_id>"}}
byCustomer: {"connect":{"email":"<Replacec_with_customer_email>"}}
review: "my product review..."
ratinng: 5.0
UniqueCustomerReview:"loggedInUser@email.com_<Poductid>" # replace the string with user email and product id. this will create a unique product review for the user alone.
      }
                   )
{
UniqueCustomerReview
# ... any requied fields
}
        }
0 голосов
/ 19 ноября 2018

Я отвечу с точки зрения MySQL. Если вы хотите обеспечить, чтобы данный клиент мог быть связан с данным продуктом только один раз, то вы должны сделать (cusotmer_id, product_id) уникальным ключом (может быть первичным) в таблице ProductReview:

ALTER TABLE ProductReview ADD UNIQUE KEY uk_cust_prod (customer_id, product_id);

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

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

...