动态构建中继查询

Posted

技术标签:

【中文标题】动态构建中继查询【英文标题】:Build relay queries dynamically 【发布时间】:2018-04-18 23:20:36 【问题描述】:

我使用 Relay Modern 作为我的客户端 GraphQL 接口。我想知道是否可以在 Relay Modern 中动态构建我的查询语句,比如更改原来的:

const ComponentQuery = graphql`
    query ComponentQuery ($companyId: ID!) 
        viewer 
            company(id: $companyId) 
                id
                name
                enabled
                users 
                    id
                    username
                    email
                    firstName
                    lastName
                    jobTitle
                    phone
                
            
        
    
`;

致以下:

let queryFields = ['name', 'enabled'];
let userFields = ['username', 'email', 'firstName', 'lastName', 'jobTitle', 'phone' ];


const ComponentQuery = graphql`
    query ComponentQuery ($companyId: ID!) 
        viewer 
            company(id: $companyId) 
                id
                queryFields
                name
                enabled
                users 
                    id
                    userFields
                
            
        
    
`;

当然,由于 GraphQL Schema 是静态的,因此所有字段都必须存在于 GraphQL Schema 中。我想要的只是动态构建查询,而不是动态的 GraphQL 架构。

【问题讨论】:

【参考方案1】:

虽然不可能像您在第二个示例中勾勒出的那样以无限的方式动态地制作查询,但您可以使用@include@skip 指令来做出固定数量的选择。

在片段级别:

query ComponentQuery(
  $companyId: ID!,
  $showUserDetails: Boolean!,
) 
  viewer 
    company(id: $companyId) 
      id
      name
      enabled
      users 
        id
        firstName
        lastName
        ... on User @include(if: $showUserDetails) 
          email
          jobTitle
          phone
          username
        
      
    
  

在字段级别:

query ComponentQuery(
  $companyId: ID!,
  $showUserContactDetails: Boolean!,
  $showUserRealName: Boolean!,
  $showUserRole: Boolean!,
  $showUserUnixname: Boolean!,
) 
  viewer 
    company(id: $companyId) 
      id
      name
      enabled
      users 
        id
        firstName @include(if: $showUserRealName)
        lastName @include(if: $showUserRealName)
        username @include(if: $showUserUnixname)
        email @include(if: $showUserContactDetails)
        jobTitle @include(if: $showUserRole)
        phone @include(if: $showUserContactDetails)
      
    
  

【讨论】:

【参考方案2】:

您在 Relay 中的所有查询和突变都需要静态可供编译器生成运行时工件。任何动态行为都需要由 graphql 变量和片段来控制。请务必仔细阅读 graphql 规范。

对于您上面的情况,片段会很好地为您服务。片段甚至可以在不同的文件中定义。我将给出一个示例,您将定义一个名为 UserComponent 的子组件,该组件将负责显示用户信息和一个指定所需字段的片段。然后,您可以在父组件查询中使用该片段。假设您正在使用 react 并且您的用户类型称为 User。

/UserComponent.js
...
const UserComponent = ( user ) => ...;
...
export default createFragmentContainer(
  ChildComponent,
  graphql`
    fragment UserComponent_user on User 
      id
      username
      email
      firstName
      lastName
      jobTitle
      phone
    
  `
);

/Component.js
const ComponentQuery = graphql`
query ComponentQuery ($companyId: ID!) 
  viewer 
    company(id: $companyId) 
      id
      name
      enabled
      users 
        ...UserComponent_user
      
    
  
`;

每次您需要渲染 UserComponent 时,请确保您在某些***查询中包含该片段。

【讨论】:

以上是关于动态构建中继查询的主要内容,如果未能解决你的问题,请参考以下文章

依赖于来自中继查询的数据的中继查询

没有数据的中继容器

动态构建Lambda表达式实现EF动态查询

如何确定中继查询是不是为空或未加载

当表名包含“'”时为 Sql Server 2008 构建动态查询

如何动态构建具有 objectId 的 mongoose 查询?