使用GraphQL检索包含具有不同模式的对象数组的对象

问题描述 投票:1回答:2

我正在尝试编写一个查询来检索具有属性linkedCards的对象,该属性包含具有不同模式的对象数组。

我有3种不同的模式(内置Contentful):

CardA示例:

{
    id: 42,
    productName: 'Laptop',
    price: 999
}

CardB示例:

{
    id: 999,
    title: 'Buy our refurbished Laptops today!'
}

CardC示例:

{
    id: 100,
    linkedCards: [
        {
            id: 42,
            productName: 'Laptop',
            price: 999
        },
        {
            id: 999,
            title: 'Buy our refurbished Laptops today!'
        }
    ]
}

查询:

allCardC() {
    nodes {
        linkedCards {
            id
            title
        }
    }
}

当我尝试运行以下GraphQL查询时,我得到"Cannot query field "title" on type "CardACardBUnion". Did you mean to use an inline fragment on "CardA" or "CardB"?"

有没有内置的方法来做到这一点,还是我可以用某种方式使用CardACardB的ID?也许有一个查询来获取linkedCards中的卡片的ID以及另一个查询来获取所述卡片?

graphql gatsby graphql-js contentful
2个回答
2
投票

如错误所示,在查询解析为联合的字段时,需要使用inline fragment

allCardC {
    nodes {
        linkedCards {
            ... on CardA {
              id
              productName
              price
            }
            ... on CardB {
              id
              title
            }
        }
    }
}

片段可以在选择集内内联定义。这样做是为了有条件地包括基于其运行时类型的字段。

与接口或常规对象类型不同,联合不指定任何特定字段,仅指定组成联合的类型。这意味着返回union的字段的选择集必须始终使用片段根据字段解析为的实际类型有条件地指定字段。

这就像说,“如果这是返回对象的实际类型,请求这些字段”。


2
投票

您可能会发现使用GraphQL interface指定每种卡类型共有的字段很有用。

interface Card {
  id: ID!
}
# type CardA implements Card { ... }
type CardB implements Card {
  id: ID!
  title: String!
}
type CardC implements Card {
  id: ID!
  linkedCards: [Card!]!
}

正如@ DanielRearden的回答所示,您仍然需要使用(内联)片段来选择特定于其中一种卡片类型的字段,但现在您知道每张卡片都有一个id字段,您可以直接选择它。

allCardC {
    nodes {
        linkedCards {
            id
            ... on CardB { title }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.