问题描述
任何帮助。
我在前端使用apollo客户端,在后端graphql-nexus使用prisma2和graphql-yoga服务器。
我想用@ paljs / plugins解决n + 1问题。
query posts{
posts {
id
favoritedBy(where: { id: { equals: $currentUserId } }) {
id
}
author {
id
avatar {
id
}
}
link {
id
}
games {
id
}
tags {
id
}
likes(where: { user: { id: { equals: $currentUserId } } }) {
id
}
}
}
帖子解析器:
import { prismaSelect } from '@paljs/plugins'
export const posts = queryField('posts',{
type: 'Post',list: true,args: {
...
},resolve: async (_parent,args,{ prisma,request },info) => {
const select = new prismaSelect(info).value
let opArgs: FindManyPostArgs = {
take: 10,orderBy: {
[args.orderBy]: 'desc',},...select
}
const post = await prisma.post.findMany(opArgs)
//The result I want to return with the "sub-models" like likes,author tags...
console.log(JSON.stringify(post,undefined,2))
return post
},})
我记录查询
const prisma = new prismaClient({
log: ['query'],})
我的问题:使用prismaSelect时,我有5个查询,而如果不检查前端的请求时间,则需要300-400ms。所以我做错了什么? 我在@paljs/plugins文档中看到了上下文中的选择。也许那是我的错误。如何在上下文中使用选择?
这里是我的上下文:
import { prismaClient,prismaClientOptions } from '@prisma/client'
import { PubSub } from 'graphql-yoga'
import { prismaDelete,onDeleteArgs } from '@paljs/plugins'
class prisma extends prismaClient {
constructor(options?: prismaClientOptions) {
super(options)
}
async onDelete(args: onDeleteArgs) {
const prismaDelete = new prismaDelete(this)
await prismaDelete.onDelete(args)
}
}
export const prisma = new prismaClient({
log: ['query'],})
export const pubsub = new PubSub()
export interface Context {
prisma: prismaClient
request: any
pubsub: PubSub
}
export function createContext(request: any): Context {
return { prisma,request,pubsub }
}
解决方法
您需要知道,要使用我的PrismaSelect
插件,您需要删除nexus-prisma-plugin
程序包,并使用我的Pal.js CLI为nexus创建您的CRUD和ObjectType并使用@paljs/nexus
插件以添加mackSchema
函数
import { makeSchema } from '@nexus/schema';
import * as types from './graphql';
import { paljs } from '@paljs/nexus'; // import our plugin
export const schema = makeSchema({
types,plugins: [paljs()],// here our plugin don't use nexus-prisma-plugin
outputs: {
schema: __dirname + '/generated/schema.graphql',typegen: __dirname + '/generated/nexus.ts',},typegenAutoConfig: {
sources: [
{
source: require.resolve('./context'),alias: 'Context',],contextType: 'Context.Context',});
现在将此类型添加到您的Context
export interface Context {
prisma: PrismaClient
request: any
pubsub: PubSub
select: any // here our select type
}
export function createContext(request: any): Context {
// our paljs plugin will add select object before resolver
return { prisma,request,pubsub,select: {} }
}
添加我们的插件后,您的查询将像这样记录
extendType({
type: 'Query',definition(t) {
t.field('findOneUser',{
type: 'User',nullable: true,args: {
where: arg({
type: 'UserWhereUniqueInput',nullable: false,}),resolve(_,{ where },{ prisma,select }) {
// our plugin add select object into context for you
return prisma.user.findOne({
where,...select,});
},});
},});
能否请您尝试使用我的pal c
命令从列表中启动示例,并尝试使用它进行模式测试
工作正常,谢谢艾哈迈德,您的插件太棒了!!!!
我从更改了后对象
const Post = objectType({
name: 'Post',definition(t) {
t.model.id()
t.model.authorId()
t.model.tags()
t.model.games()
t.model.link()
t.model.report()
t.model.notifications()
t.model.author()
t.model.favoritedBy({
filtering: {
id: true,})
t.model.likes({
filtering: {
user: true,})
}
})
到
const Post = objectType({
name: 'Post',definition(t) {
t.string('id')
t.field('tags',{
nullable: false,list: [true],type: 'Tag',resolve(parent: any) {
return parent['tags']
},})
t.field('games',{
list: [true],type: 'Game',resolve(parent: any) {
return parent['games']
},})
t.field('link',{
type: 'Link',resolve(parent: any) {
return parent['link']
},})
t.field('notifications',type: 'Notification',resolve(parent: any) {
return parent['notifications']
},})
t.field('author',type: 'User',resolve(parent: any) {
return parent['author']
},})
t.field('favoritedBy',args: {
where: 'UserWhereInput',resolve(parent: any) {
return parent['favoritedBy']
},})
t.field('likes',type: 'Like',args: {
where: 'LikeWhereInput',resolve(parent: any) {
return parent['likes']
},})
},})
我还同时使用了nexus-prisma-plugin和paljs-plugin