How to create a one-to-many relationship

Hi!

I’m excited about Redwood and hope to be involved in the community as it continues to evolve.

I’m working on a simple application to explore Redwood. It is a ‘Daily Questions’ app where you can track a handful of questions over time, inspired by the practice Marshall Goldsmith describes in his book ‘Triggers’.

What I want to accomplish is being able to create a new ‘Answer’ that I can connect to an already existing ‘Question’. I’ve been looking through various graphql, apollo, and prisma documentation to try to find the right syntax/patterns to use but am a bit confused.

Questions:

  1. How should the following files be written to successfully create a relation between an Answer and a Question?
  • AnswerInput input type in sdl file
  • createAnswer mutation type in the sdl file
  • createAnswer service in the services file
  • CREATE_ANSWER_MUTATION gql string in the NewAnswer component
  1. What documentation resources would you recommend if I were trying to answer these questions for myself?

Thanks in advance for your consideration!


Code

Model Definition

// api/prisma/schema.prisma

model Question {
  id Int @id @default(autoincrement())
  name String
  type String
  answers Answer[]
}

model Answer {
  id Int @id @default(autoincrement())
  content String
  question Question
  createdAt DateTime @default(now())
}

Schema Definition

// /api/graphql/answers.sdl.js

export const schema = gql`
  type Answer {
    id: Int!
    content: String!
    createdAt: DateTime!
    question: Question
  }

  type Query {
    answers: [Answer]
    answer(id: Int!): Answer
  }

  input AnswerInput {
    content: String
    question: Question
  }

  type Mutation {
    createAnswer(input: AnswerInput!): Answer
    updateAnswer(id: Int!, input: AnswerInput!): Answer
    deleteAnswer(id: Int!): Answer
  }
`

Service

// api/services/answers/answers.js

export const createAnswer = ({ input }) => {
  return db.answer.create({
    data: input,
  })
}

Mutation in Component

// web/src/components/NewAnswer/NewAnswer.js

const CREATE_ANSWER_MUTATION = gql`
      mutation CreateAnswerMutation($input: AnswerInput!) {
        createAnswer(input: $input) {
          id
        }
      }
    `

Hi @alex Do the following docs help you get a step closer?

Prisma2 Docs

Thanks @thedavid,

Those docs were really helpful and I’m definitely closer, but haven’t gotten it to work yet. Do you know if there exists yet a Redwood sample app that implements a 1:n relationship (e.g. User:Post, Author:Book, TodoList:Todos, etc.)?

I’m a little bit in a situation of not knowing what I don’t know, and suspect I’m missing something obvious.

Here are condensed snippets of the relevant code. This of course would not be the final implementation, I’m just trying to successfully create an Answer in the db and have it be linked to a Question. Reading all the docs you listed, I don’t see anything obvious that I’m missing.

Prisma Client

export const createAnswer = ({ input }) => {
  return db.answer.create({
    data: {
      content: input.content,
      question: {
        connect: {
          id: input.question,
        },
      },
    },
  })
}

Mutation I’m trying in Graphql Playground

    mutation {
      createAnswer(input: {
        content: "10",
        question: 2
      }) {
        id
        content
        question {
          id
          name
        }
      }
    }

Wish I had more time to help dig in! Just passing along snippets for now (sorry).

Do check out @rob’s work with posts and tags on the Example Blog (tags specific files below to start with):



Hey @alex - I know this is a bit old so you might have figured it out or moved on. But thought I would chime in to help future people that may be struggling with this. In this case - you did almost everything correct, but it should be

  input AnswerInput {
    content: String
    questionId: Int
  }

and then

export const createAnswer = ({ input }) => {
  return db.answer.create({
    data: {
      content: input.content,
      question: {
        connect: {
          id: input.questionId,
        },
      },
    },
  })
}

Hope this helps!

2 Likes

Thank you @twmilli that’s really help me to understand how to create a one-to-many relationship.
It took me some time to understand that you can’t write the “question” object inside the “input” variable because “question” cannot be on your Schema Definition Input and GraphQL give you an error for that.

I’m curious if someone knows a method to not rewrite all the key properties of your “input” inside the data object in the Service? It can be very long if you have a big object!

Thank you all again :slight_smile:

You should be able to destructure to unpack the values, like:

    const article = await db.article.create({
      data: {
        entry: {
          connectOrCreate: {
            where: { uid: parsedEntry.uid },
            create: parsedEntry,
          },
        },
        ...parsedArticle,
      },
      include: { entry: true },
    })

where parsedArticle has a number (in my case 6+) of properties.

1 Like