I'm pretty new to GraphQL and I'm trying to solve a problem that my manager has presented to me.
I have the following data structure made available to me, via a 3rd party API (Which I have zero control over):
[
{
"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:
{
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
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
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
}
}
})
}
}
}
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.