是否可以在GraphQL查询的最终响应中添加另一个字段?

时间:2018-03-23 13:53:34

标签: graphql

我一直在尝试研究如何添加GraphQL响应的另一个root属性,但在1小时后没有发现任何内容。

通常,GraphQL查询如下所示:

{
   myQuery() {
       name
   }
}

它回应:

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

我很好奇,如果我可以在此回复中添加另一个root属性,请说" meta"

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

}

这是否可行,如果不是什么是解决GraphQL方面的最佳方法?

谢谢!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

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

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;
        }
      }
    }))

答案 2 :(得分:0)

特定于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>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;
}