buforcz
buforcz

Reputation: 17

How to make self resolving array of object types with Prisma and GraphQL

Maybe the title is not accurate but I really don't know how to describe it anymore. I went through multiple documentations and descriptions but still couldn't figure it out.

I want to implement a basic social media like followers/following query on my type User. I am using MySQL and for that I made a separate table called Follow as it's a many-to-many connection.

Here is a pseudo-ish representation of my tables in the database without the unnecessary columns:

Table - User
  user_id primary key Int

Table - Follow
  follow_er foreign_key -> User(user_id) Int
  follow_ed foreign_key -> User(user_id) Int

A user could "act" as a follow_er so I can get the followed people

And a user could be follow_ed, so I can get the followers.

My prisma schema look like this:

model User {
  user_id      Int      @id @default(autoincrement())
  following    Follow[] @relation("follower")
  followed     Follow[] @relation("followed")
}

model Follow {
  follow_er      Int
  follower       User     @relation("follower", fields: [follow_er], references: [user_id])
  follow_ed      Int
  followed       User     @relation("followed", fields: [follow_ed], references: [user_id])

  @@id([follow_er, follow_ed])
  @@map("follow")
}

By implementing this I can get the followers and following object attached to the root query of the user:

const resolvers = {
    Query: {
        user: async (parent, arg, ctx) => {
            const data = await ctx.user.findUnique({
                where: {
                    user_id: arg.id
                },
                include: {
                    following: true,
                    followed:true
                }
            })
            return data
        }....

Here is my GraphQL schema I tried to make:

type Query{
    user(id: Int!): User
}

type User{
    id: ID
    following: [User]
    followed: [User]
}

So I can get something like:

query {
  user(id: $id) {
    id
    following {
       id
      }
    followed{
        id
      }
    }
  }
}

But I couldn't make it work as even if I get the the array of objects of {follow-connections}:

[
    {
        follow_er:1,
        follow_ed:2
    },
    {
        follow_er:1,
        follow_ed:3
    },
    {
        follow_er:3,
        follow_ed:1
    },
]

I can't iterate through the array. As far as I know, I have to pass either the follow_er or follow_ed, which is a user_id to get a User object.

What am I missing? Maybe I try to solve it from a wrong direction. If anybody could help me with this, or just tell me some keywords or concepts I have to look for it would be cool. Thanks!

Upvotes: 1

Views: 4144

Answers (1)

Ryan
Ryan

Reputation: 6347

I would suggest creating self-relations for this structure in the following format:

model User {
  id          Int      @id @default(autoincrement())
  name        String?
  followedBy  User[]   @relation("UserFollows", references: [id])
  following   User[]   @relation("UserFollows", references: [id])
}

And then querying as follows:

await prisma.user.findUnique({
        where: { id: 1 },
        include: { followedBy: true, following: true },
})

So you will get a response like this: find followers and following

Upvotes: 1

Related Questions