`_count` returning null from custom resolvers
art049 opened this issue · comments
Describe the Bug
When accessed through custom resolvers, the _count field is always null.
To Reproduce
Considering the following schema(I'm using mongo):
model List {
id String @id @default(auto()) @map("_id") @db.ObjectId
items ListItem[]
}
model ListItem {
id String @id @default(auto()) @map("_id") @db.ObjectId
list List @relation(fields: [listId], references: [id])
listId String @db.ObjectId
}
And this sample custom resolver:
import { List } from "@generated/type-graphql";
import { Ctx, Query, Resolver } from "type-graphql";
import { Context } from "..";
@Resolver()
export class MyListResolver {
@Query(() => List)
async mylist(@Ctx() { prisma }: Context): Promise<List> {
return await prisma.list.findFirstOrThrow();
}
}
This query:
query Mylist {
mylist {
id
_count {
items
}
}
}
Returns a null count:
{
"data": {
"mylist": {
"id": "6408705c0cd690ec08e5b690",
"_count": null
}
}
}
Expected Behavior
The query should return the actual count so:
{
"data": {
"mylist": {
"id": "6408705c0cd690ec08e5b690",
"_count": {
"items": 2
}
}
}
}
Environment (please complete the following information):
- OS: Manjaro 22.0.4
- Node
lts/gallium
typegraphql-prisma
version 0.24.2 (the issue was also there with 0.21.4)- Prisma version 4.11 (the issue was also there with 4.3.0)
- TypeScript version 4.5.4
Additional Context
I'm using MongoDB with prisma.
This feature is only available for the generated resolvers.
It's barely possible to make it working automagically for custom resolvers under the hood.
Check out the body of the generated resolvers and implement it in your custom resolvers:
async findFirstCategory(@Ctx() ctx: any, @Info() info: GraphQLResolveInfo, @Args(_returns => FindFirstCategoryArgs) args: FindFirstCategoryArgs): Promise<Category | null> {
const { _count } = transformInfoIntoPrismaArgs(info);
return getPrismaFromContext(ctx).category.findFirst({
...args,
...(_count && transformCountFieldIntoSelectRelationsCount(_count)),
});
}
You need to first read and parse the graphql resolve info to get into about requested fields in query. And then build a proper prisma args for fetching count for relations.
Okay, I thought this was an unexpected behavior.
Wouldn't it be possible to add this through the Query
decorator?
Btw, I'd be up working on this if you think it's doable
It's not possible to achieve automagically via the @Query
decorator.
The crucial part here is that we can't move this logic of transformInfoIntoPrismaArgs
and transformCountFieldIntoSelectRelationsCount
into relation resolvers (virtual _count
filed working with all queries, even custom) because Prisma relations count is coupled with the main, root db query:
https://www.prisma.io/docs/concepts/components/prisma-client/aggregation-grouping-summarizing#count-relations
So that's why the crud resolver logic is reading gql query and apply _count
part of the prisma query there.
If we moved them to the relation resolvers, we would be missing args
from the graphql query, so all the filtration would be not taken into account.
Automagic decorator also won't automagically put the _count
into your prisma.xyz.find()
call.
All you could do is to create custom param decorator that contains all the logic, so you just get _count
variable to put directly in your query.
OK now I see, we can make this working tho less optimal from query perspective 😉
@Resolver()
class UserResolver {
@Query(() => [MainUser])
async users(@Ctx() { prismaClient }: Context) {
return prismaClient.user.findMany();
}
}
@Resolver(() => MainUser)
class UserRelationsResolver {
@FieldResolver(() => MainUserCount)
async _count(
@Root() root: MainUser,
@Ctx() { prismaClient }: Context,
@Info() info: GraphQLResolveInfo,
) {
const _count = transformInfoIntoPrismaArgs(info);
const data: any = await prismaClient.user.findUniqueOrThrow({
where: { id: root.id },
...(_count && transformCountFieldIntoSelectRelationsCount(_count)),
});
return data._count;
}
}
Nice! Thanks.