GraphQL中如何无需重复内联片段获取不同内容类型的共有属性
问题解答
首先明确:Contentful 原生 GraphQL 服务默认不会为不同内容类型里的同名字段自动生成公共抽象类型,所以你不能直接凭空写...on GenericCommonFields这类查询,除非你提前做对应配置。
你有两种可选的优化方案,完全不用重复写冗余的字段查询代码:
方案1:配置Contentful内容接口(推荐,一劳永逸)
这个方案可以实现你想要的通用公共字段查询效果,利用的是Contentful自带的**内容类型组合(接口)**特性:
- 进入Contentful内容模型后台,新建一个接口类型,比如命名为
HasSlugAndName,给这个接口添加两个字段:name、slug,字段类型和你现有Page、Landing等内容类型里的同名字段保持一致。 - 逐个编辑Page、Landing、Static_Contante、Format等需要查询公共字段的内容类型,设置它们实现刚才创建的
HasSlugAndName接口,将内容类型现有的name、slug字段和接口字段做映射,这个操作不会改动已有内容的任何数据。 - 等内容模型同步生效后,查询多类型集合时就可以直接用通用内联片段,不需要为每个类型单独写字段:
# 示例:查询一个关联多类型的字段linkedCollection linkedCollection { items { ...on HasSlugAndName { name slug } } }
后续新增的内容类型只要实现这个接口,不需要修改查询代码就能自动返回name和slug字段。
方案2:零内容模型改动,复用查询片段
如果你暂时不想调整Contentful的内容模型,可以用GraphQL原生的命名片段+代码层封装减少重复代码:
- 提前把所有需要匹配的内容类型的内联片段封装成一个固定的GraphQL片段常量,所有需要查这两个字段的地方直接引用这个常量即可,不需要重复编写。
示例封装的片段内容:fragment CommonEntryFields on Entry { ...on Page { name slug } ...on Landing { name slug } ...on Static_Contante { name slug } ...on Format { name slug } } - 实际查询的时候只需要引用这个片段就行:
query GetLinkedEntries { linkedCollection { items { ...CommonEntryFields } } }
如果后续新增了带name/slug的内容类型,只需要在封装的CommonEntryFields片段里加一次对应类型的内联片段,所有引用这个片段的查询都会自动生效。如果觉得手动维护这个片段麻烦,也可以配合GraphQL代码生成工具,根据你的Contentful内容模型自动生成这个公共片段,完全不需要手写重复代码。
注意:不要尝试不写内联片段直接在多类型集合下查
name/slug,Contentful的GraphQL层会直接报字段不存在的错误,因为集合的根返回类型是通用Entry接口,只包含sys等系统字段,不包含你自定义的业务字段。
内容的提问来源于stack exchange,提问作者Zenek Wiaderko
相关产品推荐
相关产品推荐

