GraphQL ObjectType,包含基于参数的动态字段 [英] GraphQL ObjectType with dynamic fields based on arguments

查看:576
本文介绍了GraphQL ObjectType,包含基于参数的动态字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的情况是GraphQL Query的响应必须返回对象的一些动态属性。在我们的例子中,我们无法预定义所有可能的属性 - 因此它必须是动态的。

We are in the situation that the response of our GraphQL Query has to return some dynamic properties of an object. In our case we are not able to predefine all possible properties - so it has to be dynamic.

我们认为有两种方法可以解决它。

As we think there are two options to solve it.

const MyType = new GraphQLObjectType({
  name: 'SomeType',
  fields: {
    name: {
      type: GraphQLString,
    },
    elements: {
      /*
      THIS is our special field which needs to return a dynamic object 
      */
    },
    // ...
  },
});

正如您在示例代码中看到的那样,元素是必须返回对象的属性。解决此问题时的响应可能是:

As you can see in the example code is element the property which has to return an object. A response when resolve this could be:

{
  name: 'some name',
  elements: {
    an_unkonwn_key: {
      some_nested_field: {
        some_other: true,
      },
    },
    another_unknown_prop: 'foo',
  },
}

1)返回Any-Object

我们可以返回任何对象 - 因此GraphQL不需要知道Object有哪些字段。当我们告诉GraphQL该字段是GraphQlObjectType类型时,它需要定义字段。因此,似乎无法告诉GraphQL某人只是一个对象。

We could just return any object - so GraphQL do not need to know which fields the Object has. When we tell GraphQL that the field is the type GraphQlObjectType it needs to define fields. Because of this it seems not to be possible to tell GraphQL that someone is just an Object.

我们已经改变了这个:

elements: {
      type: new GraphQLObjectType({ name: 'elements' });
    },

2)我们可以定义动态字段属性,因为它在函数

当我们将字段定义为函数时,我们可以动态定义对象。但是字段函数需要一些信息(在我们的例子中,信息将传递给元素),我们需要访问它们来构建字段对象。

When we define fields as an function we could define our object dynamically. But the field function would need some information (in our case information which would be passed to elements) and we would need to access them to build the field object.

示例:

const MyType = new GraphQLObjectType({
  name: 'SomeType',
  fields: {
    name: {
      type: GraphQLString,
    },
    elements: {
      type: new GraphQLObjectType({
        name: 'elements',
        fields: (argsFromElements) => {
          // here we can now access keys from "args"
          const fields = {};
          argsFromElements.keys.forEach((key) => {
            // some logic here ..
            fields[someGeneratedProperty] = someGeneratedGraphQLType;
          });
          return fields;
        },
      }),
      args: {
        keys: {
          type: new GraphQLList(GraphQLString),
        },
      },
    },
    // ...
  },
});

这可行,但问题是如果有办法传递args和/或解决对象到字段。

This could work but the question would be if there is a way to pass the args and/or resolve object to the fields.

问题
所以我们现在的问题是:在GraphQL中我们建议采用哪种方式,解决方案1或2可能吗?也许有另一种解决方案?

Question So our question is now: Which way would be recommended in our case in GraphQL and is solution 1 or 2 possible ? Maybe there is another solution ?

编辑
使用ScalarType时,解决方案1可以正常工作。示例:

Edit Solution 1 would work when using the ScalarType. Example:

type: new GraphQLScalarType({
        name: 'elements',
        serialize(value) {
          return value;
        },
      }),

我不确定这是否是推荐的方法来解决我们的情况。

I am not sure if this is a recommended way to solve our situation.

推荐答案

这两种选择都不可行:


  1. GraphQL是强类型的。 GraphQL.js不支持某种任何字段,并且架构中定义的所有类型都必须定义字段。 如果您查看文档字段是必需的 - 如果你试图将其删除,你就会遇到错误。

  1. GraphQL is strongly typed. GraphQL.js doesn't support some kind of any field, and all types defined in your schema must have fields defined. If you look in the docs, fields is a required -- if you try to leave it out, you'll hit an error.

Args用于解决每个问题的查询 - 请求基础。您无法将它们传递回您的架构。你的架构应该是静态的。

Args are used to resolve queries on a per-request basis. There's no way you can pass them back to your schema. You schema is supposed to be static.

如你所知,你可以完成你想做的事情通过滚动自己的客户Scalar。我认为更简单的解决方案就是使用JSON - 您可以像这样导入自定义标量一个。然后让您的元素字段解析为包含动态字段的JSON对象或数组。如果需要,您还可以根据参数操作解析程序内的JSON对象(例如,如果要将返回的字段限制为args中定义的子集)。

As you suggest, it's possible to accomplish what you're trying to do by rolling your own customer Scalar. I think a simpler solution would be to just use JSON -- you can import a custom scalar for it like this one. Then just have your elements field resolve to a JSON object or array containing the dynamic fields. You could also manipulate the JSON object inside the resolver based on arguments if necessary (if you wanted to limit the fields returned to a subset as defined in the args, for example).

警告词:利用JSON或包含嵌套数据的任何自定义标量的问题在于,限制了客户端在请求实际需要时的灵活性。它还会导致客户端上的错误更少 - 我更倾向于被告知我请求的字段不存在或在我发出请求时返回null 而不是稍后查找我得到的JSON blob的行不包括我期望它的字段。

Word of warning: The issue with utilizing JSON, or any custom scalar that includes nested data, is that you're limiting the client's flexibility in requesting what it actually needs. It also results in less helpful errors on the client side -- I'd much rather be told that the field I requested doesn't exist or returned null when I make the request than to find out later down the line the JSON blob I got didn't include a field I expected it to.

这篇关于GraphQL ObjectType,包含基于参数的动态字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆