I am trying to write a query to retrieve an object with the property linkedCards
that contains an array of objects with different schemas.
I have 3 different schemas (built in Contentful):
CardA example:
{
id: 42,
productName: 'Laptop',
price: 999
}
CardB example:
{
id: 999,
title: 'Buy our refurbished Laptops today!'
}
CardC example:
{
id: 100,
linkedCards: [
{
id: 42,
productName: 'Laptop',
price: 999
},
{
id: 999,
title: 'Buy our refurbished Laptops today!'
}
]
}
Query:
allCardC() {
nodes {
linkedCards {
id
title
}
}
}
When I try to run the following GraphQL query I get
"Cannot query field "title" on type "CardACardBUnion". Did you mean to use an inline fragment on "CardA" or "CardB"?"
Is there a built-in way to do this or can I use the ids of CardA
& CardB
somehow? Perhaps have one query to get the ids of the cards in linkedCards
and another query to get said cards?
const express = require("express"); const graphqlHTTP = require("express-graphql"); const schema = require("./schema/schema"); const app = express(); app. use("/graphql", graphqlHTTP({ schema, graphiql: true })); app. listen(4000, () => { console.
GraphQL provides a query language to define the shape of data you'd like returned from an HTTP API on a server and a library to help make it happen. It's easy to return a single item or multiple items.
As the error indicates, you need to use an inline fragment when querying a field that resolves to a union:
allCardC {
nodes {
linkedCards {
... on CardA {
id
productName
price
}
... on CardB {
id
title
}
}
}
}
Fragments can be defined inline within a selection set. This is done to conditionally include fields based on their runtime type.
Unlike interfaces or regular object types, unions do not specify any particular fields, only the types that make up the union. That means a selection set for a field that returns a union must always use fragments to conditionally specify the fields depending on the actual type that the field resolves to.
It's like saying, "if this is the actual type of the returned object, request these fields".
You may find it useful to use a GraphQL interface to specify the fields that every card type has in common.
interface Card {
id: ID!
}
# type CardA implements Card { ... }
type CardB implements Card {
id: ID!
title: String!
}
type CardC implements Card {
id: ID!
linkedCards: [Card!]!
}
As @DanielRearden's answer suggests you still need to use (inline) fragments to select fields that are specific to one of the card types, but now that you know every card has an id
field, you can select that directly.
allCardC {
nodes {
linkedCards {
id
... on CardB { title }
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With