【问题标题】:Prisma2: How to solve n +1 Problem with PaljsPrisma2:如何用 Paljs 解决 n+1 问题
【发布时间】:2021-01-22 15:27:08
【问题描述】:

感谢任何帮助。

我在前端使用 apollo-client 和后端 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 个查询,如果我在前端检查请求时间,我需要 PrismaSelect 多 300-400 毫秒。那么我做错了什么? 我在@paljs/plugins doc 中看到了上下文中的选择。也许那是我的错误。如何在上下文中使用 select?

这是我的上下文:

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 }
}

【问题讨论】:

    标签: graphql apollo-client prisma2


    【解决方案1】:

    您需要知道要使用我的PrismaSelect 插件,您需要删除nexus-prisma-plugin 包并使用我的Pal.js CLI 为nexus 创建您的CRUD 和ObjectType,并使用@paljs/nexus 插件添加@987654324 @函数

    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 命令从我的列表中启动一个示例并尝试您的架构并使用它进行测试

    【讨论】:

      【解决方案2】:

      它正在工作,谢谢 Ahmed 你的插件太棒了!!!!!

      我从

      更改了我的 Post-Object
      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',
            nullable: true,
            resolve(parent: any) {
              return parent['link']
            },
          })
          t.field('notifications', {
            list: [true],
            type: 'Notification',
            resolve(parent: any) {
              return parent['notifications']
            },
          })
          t.field('author', {
            nullable: false,
            type: 'User',
            resolve(parent: any) {
              return parent['author']
            },
          })
          t.field('favoritedBy', {
            nullable: false,
            list: [true],
            type: 'User',
            args: {
              where: 'UserWhereInput',
            },
            resolve(parent: any) {
              return parent['favoritedBy']
            },
          })
          t.field('likes', {
            list: [true],
            type: 'Like',
            args: {
              where: 'LikeWhereInput',
            },
            resolve(parent: any) {
              return parent['likes']
            },
          })
        },
      })
      

      而且我还同时使用了nexus-prisma-plugin和paljs-plugin

      【讨论】:

      • 但是我能知道你在哪里使用nexus-prisma-plugin吗?并且不要自行转换类型,您可以使用我的@paljs/cli pal g 命令自动生成所有类型
      • 我使用了nexus-prisma-plugin。现在我正在使用 paljs。 pal g 命令很棒。使它非常容易和富有成效。再次感谢。我对帖子的回答是没有@paljs/cli。但现在我将 @paljs/cli 与 generate 命令一起使用。
      • 很高兴为您提供帮助
      猜你喜欢
      • 2011-02-05
      • 2021-08-27
      • 2015-02-12
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      • 2018-05-20
      • 2021-12-10
      • 2021-04-26
      相关资源
      最近更新 更多