I want to query for posts and for each post I wan't just the like from the current user.
I have 2 solutions and both are working. But which one is better? Or are there better solutions?
- Frontend: React + ApolloClient
- Backend: Primsa2 + Graphql Nexus
Prisma Schema:
model Post {
id String @id @default(cuid())
likes Like[]
}
model Like {
id String @id @default(cuid())
post Post? @relation(fields: [postId], references: [id])
postId String?
user User @relation(fields: [userId], references: [id])
userId String
}
model User {
id String @id @default(cuid())
likes Like[]
}
The queryField is the same for both solutions:
export const posts = queryField('posts', {
type: 'Post',
list: true,
resolve: async (_parent, args: any, { prisma, request }, info) => {
opArgs={
//unimportant
}
return prisma.post.findMany(opArgs)
},
})
- Solution: I make a request with the where condition for the like direct in the query with apollo client
Frontend: ApolloClient
const POSTS_USER = gql`
query posts(
$currentUserId: String
) {
posts {
id
likes(where: { user: { id: { equals: $currentUserId } } }) { // where condition!
id
}
}
}
`;
const POSTS_NO_USER = gql`
query posts(
$currentUserId: String
) {
posts {
id
}
}
`;
const { data, loading } = useQuery(user? POSTS_USER: POSTS_NO_USER, {
variables: {
currentUserId: user ? user.id : "",
},
});
Backend Nexus Object:
const Post = objectType({
name: 'Post',
definition(t) {
t.model.id()
t.model.likes({
filtering: {
user: true,
},
})
},
})
- Solution: I make for the objectType Post a field condition for the likes.
Frontend: ApolloClient
const POSTS = gql`
query posts {
posts {
id
likes { // NO where condition!
id
}
}
}
`;
const { data, loading } = useQuery(POSTS);
Backend with Nexus:
const Post = objectType({
name: 'Post',
definition(t) {
t.model.id()
t.model.likes()
t.list.field('likes', {
type: 'Like',
list: true,
resolve: (parent, args, { prisma, request }) => {
const user = getUser(request, false)
if (!user) {
return []
} else {
return prisma.like.findMany({
where: {
postId: parent.id,
userId: user.id,
},
})
}
},
})
},
})
The first way is better why?
when you make the first query prisma will do your query in 1 DB query. when you make the second query you will have DB queries as you have posts number
And the best way to use my PrismaSelect plugin Prisma Select takes the
info: GraphQLResolveInfo
object in general graphql arguments (parent, args, context, info) to select object accepted byprisma client
. The approach allows a better performance since you will only be using one resolver to retrieve all your request. By doing so, it also eliminates theN + 1
issue.But you also will need to drop using nexus-plugin-prisma and use my pal.js CLI to auto-generate your CRUD