【问题标题】:Is it possible to add another field in the final response of GraphQL query?是否可以在 GraphQL 查询的最终响应中添加另一个字段?
【发布时间】:2018-09-02 05:21:41
【问题描述】:

我一直在尝试研究如何添加 GraphQL 响应的另一个根属性,但 1 小时后一无所获。

通常,GraphQL 查询如下所示:

{
   myQuery() {
       name
   }
}

它的响应是:

{
    "data": {
       "myQuery": []
    }
}

我很好奇是否可以在此响应中添加另一个根属性说“元”

{
    "data": {
       "myQuery": []
    },
    "meta": {
       "page": 1,
       "count": 10,
       "totalItems": 90
     }

}

这可能吗?如果不是,那么在 GraphQL 方面解决这个问题的最佳方法是什么?

谢谢!

【问题讨论】:

标签: graphql


【解决方案1】:

apollo-server 中间件可以配置多个配置选项,包括允许您修改传出 GraphQL 响应的 formatResponse 函数

const formatResponse = (response) => {
  return {
    meta
    ...response
  }
}

app.use('/graphql', bodyParser.json(), graphqlExpress({
  schema,
  formatResponse,
}));

您可以将 req 对象传递给您的上下文,在您的解析器中对其进行变异,然后在 formatResponse 中使用结果。比如……

app.use('/graphql', bodyParser.json(), (req, res, next) => graphqlExpress({
  schema,
  formatResponse: (gqlResponse) => ({
    ...gqlResponse
    meta: req.metadata
  }),
})(req, res, next));

不过,通常情况下,您希望将元数据作为实际架构的一部分包含在数据中。这也将允许您潜在地请求多个查询并获取所有查询的元数据。

有多种方法可以做到这一点,具体取决于您的数据结构,但这里有一个示例:

type Query {
  getFoos: QueryResponse
  getBars: QueryResponse  
}

type QueryResponse {
  results: [Result]
  meta: MetaData
}

union Result = Bar | Foo

【讨论】:

  • 感谢您扩展 formatResponse 答案并使用模式显示替代方案。将此作为最佳答案。
【解决方案2】:

您也可以在响应中添加任何内容...请按照以下代码进行操作。

app.use('/graphql', bodyParser.json(), graphqlExpress(req => {
      return {
        schema: tpSchemaNew,
        context: {
          dbModel
        },
        formatError: err => {
          if (err.originalError && err.originalError.error_message) {
            err.message = err.originalError.error_message;
          }
          return err;
        },
        formatResponse : res => {
          res['meta'] = 'Hey';
          return res;
        }
      }
    }))

【讨论】:

    【解决方案3】:

    Apollo 服务器特定:

    在前面的答案中添加formatResponse() 有另一个有用的参数requestContext

    如果您有兴趣从中提取值(例如,传递给解析器的上下文),您可以执行以下操作。但请注意,上下文可能包含本应为私有的敏感数据。如果不小心,您可能会泄露身份验证数据和机密。

    const server = new ApolloServer({
      schema,
      formatResponse: (response, requestContext) => {
        //return response
        
        const userId = requestContext.context.user.id
        
        response = Object.assign(response, {
          extensions: {
            meta: {
              userId: userId
            }
          }
        }
    
        return response
      },
    })
    

    上面将在 gql 查询响应中返回类似这样的内容(注意扩展对象):

    {
      data: {
        user: {
          firstName: 'Hello',
          lastName: 'World'
        }
      },
      extensions: { // <= in Typescript, there is no `meta` in GraphQLResponse, but you can use extensions
        meta: {
          userId: 1234 //<= data from the context
        }
      }
    }
    

    requestContext 中可用属性的完整列表: 在node_modules/apollo-server-types/src/index.ts&gt;GraphQLRequestContext

    export interface GraphQLRequestContext<TContext = Record<string, any>> {
      readonly request: GraphQLRequest;
      readonly response?: GraphQLResponse;
    
      readonly context: TContext;
      readonly cache: KeyValueCache;
    
      // This will be replaced with the `operationID`.
      readonly queryHash?: string;
    
      readonly document?: DocumentNode;
      readonly source?: string;
    
      // `operationName` is set based on the operation AST, so it is defined even if
      // no `request.operationName` was passed in.  It will be set to `null` for an
      // anonymous operation, or if `requestName.operationName` was passed in but
      // doesn't resolve to an operation in the document.
      readonly operationName?: string | null;
      readonly operation?: OperationDefinitionNode;
    
      /**
       * Unformatted errors which have occurred during the request. Note that these
       * are present earlier in the request pipeline and differ from **formatted**
       * errors which are the result of running the user-configurable `formatError`
       * transformation function over specific errors.
       */
      readonly errors?: ReadonlyArray<GraphQLError>;
    
      readonly metrics?: GraphQLRequestMetrics;
    
      debug?: boolean;
    }
    

    【讨论】:

    • 请注意,如果您使用的是 Typescript,GraphQLResponse 类型中没有 meta 键。您需要将meta 放在extensions 中,如上例所示
    猜你喜欢
    • 2018-10-31
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    • 1970-01-01
    • 2017-09-17
    相关资源
    最近更新 更多