简体   繁体   English

在graphql中构建嵌套结构

[英]Building a nested structure in graphql

I'm pretty new to GraphQL and I'm trying to solve a problem that my manager has presented to me. 我是GraphQL的新手,我正在尝试解决我的经理向我提出的问题。

I have the following data structure made available to me, via a 3rd party API (Which I have zero control over): 通过第三方API(我无法控制),我可以使用以下数据结构:

[
  {
    "id": 19,
    "date": "2016-10-24T13:59:19",
    "date_gmt": "2016-10-24T12:59:19",
    "slug: "data",
    "provider": {
      "name": "data",
      "logo": "data",
      "destination_url": "data",
      "coupon_label": "data",
      "coupon_text": "data",
      "coupon_code": "data",
      "coupon_url": "data",
    }
  }
]

I need to turn it into a GraphQL schema which looks like the following query: 我需要把它变成一个GraphQL模式,看起来像下面的查询:

{
  provider(slug: "slug") {
    id
    date
    slug
    name
    logo
    url
    coupon {
      label
      text
      code
      url
    }
  }
}

I've managed to sort most of it out with the code below, however, I can't work out how to group the coupon nodes into one. 我已经设法使用下面的代码对大部分内容进行排序,但是,我无法弄清楚如何将优惠券节点分组为一个。

I am guessing this need to be another custom type? 我猜这需要另一个自定义类型? If so this seems inefficient as coupon will never be used outside of the provider type so I wanted to know if there was a more 'best practice' way of doing it that I'm not aware of. 如果是这样,这似乎是低效的,因为优惠券永远不会在提供者类型之外使用,所以我想知道是否有更多的“最佳实践”方式,我不知道。

import { GraphQLObjectType, GraphQLInt, GraphQLString } from 'graphql'

const ProviderType = new GraphQLObjectType({
  name: 'Provider',
  fields: () => ({
    id: {
      type: GraphQLInt,
      description: 'The primary key for the provider'
    },
    slug: {
      type: GraphQLString,
      description: 'A unique string for the provider'
    },
    status: {
      type: GraphQLString,
      description: 'The the published status of the provider'
    },
    name: {
      type: GraphQLString,
      description: 'The name of the provider',
      resolve (parent) { return parent.provider.name }
    },
    logo: {
      type: GraphQLString,
      description: 'The full url of the provider logo',
      resolve (parent) { return parent.provider.logo }
    },
    url: {
      type: GraphQLString,
      description: 'The full url of the provider',
      resolve (parent) { return parent.provider.destination_url }
    },
  })
})

export default ProviderType

Update: 更新:

I've updated the code to the following but it's still not working, so my assumption must have been incorrect (or I implemented it incorrectly) 我已经将代码更新为以下内容但它仍然无效,所以我的假设一定是不正确的(或者我错误地实现了它)

const ProviderType = new GraphQLObjectType({
  name: 'Provider',
  fields: () => ({
    id: {
      type: GraphQLInt,
      description: 'The primary key for the provider'
    },
    slug: {
      type: GraphQLString,
      description: 'A unique string for the provider'
    },
    status: {
      type: GraphQLString,
      description: 'The the published status of the provider'
    },
    name: {
      type: GraphQLString,
      description: 'The name of the provider',
      resolve (parent) { return parent.provider.name }
    },
    logo: {
      type: GraphQLString,
      description: 'The full url of the provider logo',
      resolve (parent) { return parent.provider.logo }
    },
    url: {
      type: GraphQLString,
      description: 'The full url of the provider',
      resolve (parent) { return parent.provider.destination_url }
    },
    coupon: {
      type: CouponType,
      description: 'The coupon information for the provider'
    }
  })
})

const CouponType = new GraphQLObjectType({
  name: 'Coupon',
  fields: () => ({
    label: {
      type: GraphQLString,
      description: 'The label for the coupon',
      resolve (parent) { return parent.provider.coupon_label }
    },
    text: {
      type: GraphQLString,
      description: 'The text for the coupon',
      resolve (parent) { return parent.provider.coupon_text }
    },
    code: {
      type: GraphQLString,
      description: 'The code for the coupon',
      resolve (parent) { return parent.provider.coupon_code }
    },
    url: {
      type: GraphQLString,
      description: 'The url for the coupon',
      resolve (parent) { return parent.provider.coupon_url }
    }
  })
})

Your schema is mostly correct, but you need a resolver on your coupon field in provider because it is a nested type. 您的架构大多是正确的,但您需要在提供程序中的优惠券字段上使用解析程序,因为它是嵌套类型。 See launchpad example for interactive query https://launchpad.graphql.com/r995kzj5kn 有关交互式查询,请参阅launchpad示例https://launchpad.graphql.com/r995kzj5kn

and here is the code. 这是代码。 I have removed your descriptions for brevity and added some test data 为简洁起见,我删除了您的描述并添加了一些测试数据

import {
  GraphQLObjectType,
  GraphQLSchema,
  GraphQLString,
  GraphQLInt,
  GraphQLList
} from 'graphql'

const data = [
  {
    "id": 19,
    "date": "2016-10-24T13:59:19",
    "date_gmt": "2016-10-24T12:59:19",
    "slug": "slug",
    "provider": {
      "name": "provider.name",
      "logo": "provider.logo",
      "destination_url": "provider.destination_url",
      "coupon_label": "provider.coupon_label",
      "coupon_text": "provider.coupon_text",
      "coupon_code": "provider.coupon_code",
      "coupon_url": "provider.coupon_url",
    }
  },
    {
    "id": 20,
    "date": "2016-10-24T13:59:19",
    "date_gmt": "2016-10-24T12:59:19",
    "slug": "slugplug",
    "provider": {
      "name": "provider.name",
      "logo": "provider.logo",
      "destination_url": "provider.destination_url",
      "coupon_label": "provider.coupon_label",
      "coupon_text": "provider.coupon_text",
      "coupon_code": "provider.coupon_code",
      "coupon_url": "provider.coupon_url",
    }
  }
]

const CouponType = new GraphQLObjectType({
  name: 'Coupon',
  fields: () => ({
    label: {
      type: GraphQLString,
      resolve (parent) { return parent.provider.coupon_label }
    },
    text: {
      type: GraphQLString,
      resolve (parent) { return parent.provider.coupon_text }
    },
    code: {
      type: GraphQLString,
      resolve (parent) { return parent.provider.coupon_code }
    },
    url: {
      type: GraphQLString,
      resolve (parent) { return parent.provider.coupon_url }
    }
  })
})

const ProviderType = new GraphQLObjectType({
  name: 'Provider',
  fields: () => ({
    id: { type: GraphQLInt },
    date: { type: GraphQLString },
    slug: { type: GraphQLString },
    status: { type: GraphQLString },
    name: {
      type: GraphQLString,
      resolve (parent) { return parent.provider.name }
    },
    logo: {
      type: GraphQLString,
      resolve (parent) { return parent.provider.logo }
    },
    url: {
      type: GraphQLString,
      resolve (parent) { return parent.provider.destination_url }
    },
    coupon: {
      type: CouponType,
      resolve(parent) {
        return parent
      }
    }
  })
})

const Query = new GraphQLObjectType({
  name: 'Query',
  fields: {
    provider: {
      type: new GraphQLList(ProviderType),
      args: {
        slug: { type: GraphQLString }
      },
      resolve (source, args) {
        return args.slug ?
          data.filter(({ slug }) => slug === args.slug) :
          data
      }
    }
  }
})

const schema = new GraphQLSchema({
  query: Query
});

alternately you can just modify the results in the root resolver before sending them down like the following. 或者,你可以在发送它们之前修改根解析器中的结果,如下所示。 this would allow you to remove all the resolvers from your types except for coupon on provider which would just return parent.coupon 这将允许您从您的类型中删除所有解析器,除了提供商的coupon ,只会返回parent.coupon

const Query = new GraphQLObjectType({
  name: 'Query',
  fields: {
    provider: {
      type: new GraphQLList(ProviderType),
      args: {
        slug: { type: GraphQLString }
      },
      resolve (source, args) {
        const filtered = args.slug ?
          data.filter(({ slug }) => slug === args.slug) :
          data
        return filtered.map(doc => {
          return {
            id: doc.id,
            date: doc.date,
            slug: doc.slug,
            name: doc.provider.name,
            logo: doc.provider.logo,
            url: doc.provider.coupon_url,
            coupon: {
              label: doc.provider.coupon_label,
              text: doc.provider.coupon_text,
              code: doc.provider.coupon_code,
              url: doc.provider.coupon_url
            }
          }
        })
      }
    }
  }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM