无法用Primsa在GraphQL-yoga上使用碎片。[英] Unable to use Fragments on GraphQL-yoga with Primsa

本文是小编为大家收集整理的关于无法用Primsa在GraphQL-yoga上使用碎片。的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在使用带有 Prisma 和 Prisma-Bindings 的 graphql-yoga

我正在尝试向我的解析器添加一个片段,以便在用户请求自定义字段 costToDate 时始终获取特定字段(在这种情况下为 id).

这样我就可以进行一些额外的查询来构建该字段的结果,并且我需要该对象的 ID.

不幸的是,我似乎无法让它工作,而且文档似乎有点缺乏关于 graphql-yoga 和 Prisma 的细节.

这里是类型的定义:

type Job {
    id: ID!
    projectNumber: String!
    client: Client!
    name: String!
    description: String
    quoteNumber: String
    workshopDaysQuoted: String!
    quoted: String!
    targetSpend: String!
    costs: [JobCost!]!
    estimatedCompletion: DateTime
    completed: Boolean!
    costTotal: String
    workshopDaysUsed: String
    costsToDate: String
}

这里是查询的解析器:

const jobs = {
    fragment: `fragment description on Jobs { id }`,
    resolve: jobsResolver
}

async function jobsResolver(root, args, context, info) {
    await validatePermission(args,context,info,['admin','user','appAuth'])
    const {showCompleted} = args
    const completedFilter = (typeof showCompleted === 'boolean') ? { completed: showCompleted } : {}
    const jobIDS = await context.db.query.jobs({ where: completedFilter }, `{ id }`)
    //console.log(jobIDS);
    let jobs = await context.db.query.jobs({
        where: completedFilter
    }, info)
    return  await getAllJobCostsToDateList(jobs)
}

我正在按照下面的方式应用 fragmentReplacements.

const fragmentReplacements = extractFragmentReplacements(resolvers)

console.log(fragmentReplacements)

const port = process.env.PORT || 3010

const graphQLServer = new GraphQLServer({
    typeDefs: './src/schema.graphql',
    resolvers,
    resolverValidationOptions: {
        requireResolversForResolveType: false
    },
    context: req => ({
        ...req,
        db: new Prisma({
            typeDefs: `src/generated/prisma.graphql`,
            fragmentReplacements,
            endpoint: PRISMA_ENDPOINT,
            secret: PRISMA_KEY,
            debug: false
        })
    })
})

如果我控制台记录 fragmentReplacements 对象,我会得到以下信息,所以它似乎确实在拾取碎片.

[ { field: 'job', fragment: 'fragment costsToDate on Job { id }' },
  { field: 'jobs',
    fragment: 'fragment costsToDate on Jobs { id }' } ]

所以我的期望是,如果我对要求 costToDate 字段的作业或作业进行查询,它还将获取作业/每个作业的 id.

但是,如果我进行以下查询.

query{
  jobs{
    description
    costsToDate
  }
}

但是我没有看到 id 被获取,并且解析器函数的根参数中没有任何内容.

抱歉,因为我可能在这里完全错误地吠叫了树,这似乎是一个有点简单的要求,但我无法完全解决.当然我错过了一些基本的东西.

谢谢!

加雷斯

推荐答案

片段用于始终检索给定类型上的给定字段>.

它遵循以下格式:

fragment NameOfYourFragment on YourType { ... }

您目前不能有条件地应用给定的片段,因为它总是被应用.此外,您在 Jobs 上指定了一个片段,但 Prisma 使用的类型名称是 Job(即使您有 job 和 jobs 解析器)

您可能只需要以下解析器:

const job = {
  fragment: `fragment JobId on Job { id }`,
  resolve: jobsResolver
}

本文地址:https://www.itbaoku.cn/post/1938157.html

问题描述

I am using graphql-yoga with Prisma and Prisma-Bindings

I'm trying to add a fragment to my resolver so that a specific field (id in this situation) is always fetched when the user asks for a custom field, costsToDate.

This is so i can make some additional queries needed to build the result for that field, and i need the ID of the object for that.

Unfortunatley i can't seem to get it to work, and the documentations seems a little lacking on the specifics with graphql-yoga and Prisma.

Here is the definition of the type:

type Job {
    id: ID!
    projectNumber: String!
    client: Client!
    name: String!
    description: String
    quoteNumber: String
    workshopDaysQuoted: String!
    quoted: String!
    targetSpend: String!
    costs: [JobCost!]!
    estimatedCompletion: DateTime
    completed: Boolean!
    costTotal: String
    workshopDaysUsed: String
    costsToDate: String
}

And here is the resolver for the query:

const jobs = {
    fragment: `fragment description on Jobs { id }`,
    resolve: jobsResolver
}

async function jobsResolver(root, args, context, info) {
    await validatePermission(args,context,info,['admin','user','appAuth'])
    const {showCompleted} = args
    const completedFilter = (typeof showCompleted === 'boolean') ? { completed: showCompleted } : {}
    const jobIDS = await context.db.query.jobs({ where: completedFilter }, `{ id }`)
    //console.log(jobIDS);
    let jobs = await context.db.query.jobs({
        where: completedFilter
    }, info)
    return  await getAllJobCostsToDateList(jobs)
}

I am applying the the fragmentReplacements as per below.

const fragmentReplacements = extractFragmentReplacements(resolvers)

console.log(fragmentReplacements)

const port = process.env.PORT || 3010

const graphQLServer = new GraphQLServer({
    typeDefs: './src/schema.graphql',
    resolvers,
    resolverValidationOptions: {
        requireResolversForResolveType: false
    },
    context: req => ({
        ...req,
        db: new Prisma({
            typeDefs: `src/generated/prisma.graphql`,
            fragmentReplacements,
            endpoint: PRISMA_ENDPOINT,
            secret: PRISMA_KEY,
            debug: false
        })
    })
})

If i console.log the fragmentReplacements object i get the following, so it does seem to be picking up the fragments.

[ { field: 'job', fragment: 'fragment costsToDate on Job { id }' },
  { field: 'jobs',
    fragment: 'fragment costsToDate on Jobs { id }' } ]

So my expectation here is that if i make a query against jobs or job that asks for the costsToDate field that it will also fetch the id for the job/each job.

However if i make the following query.

query{
  jobs{
    description
    costsToDate
  }
}

But i see no id fetched, and nothing in the root parameter on the resolver function.

Apologies as i am probably barking up completely the wrong tree here, seems like a somewhat simple requirement, but i can't quite work it out. Sure i'm missing something fundamental.

Thanks!

Gareth

推荐答案

A fragment is used to always retrieve given fields on a given type.

It follows the following format:

fragment NameOfYourFragment on YourType { ... }

You currently can't apply a given fragment conditionally as it is always applied. Moreover, you specified a fragment on Jobs, but the type name used by Prisma is Job (even if you have the job and jobs resolvers)

You probably only need the following resolver:

const job = {
  fragment: `fragment JobId on Job { id }`,
  resolve: jobsResolver
}