5

是否可以动态创建 GraphQL 模式?

我们将数据存储在 mongoDB 中,并且有可能添加新字段。我们不希望 mongoDB 文档中这个新添加的字段发生任何代码更改。

有什么方法可以动态生成模式?

Schema 是在代码中定义的,但是对于 java(schema as pojo),当添加新属性时,您必须更新并重新编译代码,然后再次归档和部署 jar。有什么方法可以通过数据生成架构而不是预先定义它?

目前我们正在使用java相关项目(graphql-javagraphql-java-annotations)进行 GraphQL 开发。

4

2 回答 2

8

您可以使用graphql-spqr,它允许您根据服务类自动生成模式。在您的情况下,它看起来像这样:

public class Pojo {

    private Long id;
    private String name;

    // whatever Ext is, any (complex) object would work fine
   private List<Ext> exts;
}

public class Ext {
    public String something;
    public String somethingElse;
}

大概,您有​​一个包含您的业务逻辑的服务类:

public class PojoService {

    //this could also return List<Pojo> or whatever is applicable
    @GraphQLQuery(name = "pojo")
    public Pojo getPojo() {...}
}

要公开此服务,您只需执行以下操作:

GraphQLSchema schema = new GraphQLSchemaGenerator()
                .withOperationsFromSingleton(new PojoService())
                .generate();

然后,您可以触发查询,例如:

query test {
    pojo {
        id
        name 
        exts {
            something
            somethingElse
        } } }

不需要奇怪的包装器或任何类型的自定义代码,也不需要牺牲类型安全。适用于泛型、依赖注入或您项目中可能拥有的任何其他爵士乐。

全面披露:我是graphql-spqr的作者。

于 2017-05-27T12:10:27.903 回答
0

经过几天的调查。我发现很难在 Java 中动态生成模式(或者成本太高)。

嗯,从另一种方式。我认为我们可以使用Map一种妥协的方式来实现这一点。

  • POJO/实体

    public class POJO{
        @GraphQLField
        private Long id;
    
        @GraphQLField
        private String name;
    
        // ...
    
        @GraphQLField
        private GMap exts;   
    }
    

    GMap 是一个自定义的 Map(因为 Map/HashMap 是一个 JDK 内部类,它不能作为 GraphQL Schema,只能扩展)。

  • 地图

    public class GMap extends HashMap<String, String> {
    
        @GraphQLField
        public String get(@GraphQLName("key") String key) {
            return super.get(key);
        }
    }
    
  • 从客户端检索数据

    // query script
    query test
    {
        your_method
        {
            id
            name
            exts {
                get(key: "ext") // Add a extended attribute someday
            }
        }
    }
    
    // result 
    {
        "errors":[],
        "data":
        {
            "list":
            [
                {"id":1, name: "name1", exts: {"get": "ext1"}},
                {"id":2, name: "name2", exts: {"get": "ext2"}}
            ]
        }
    }
    
于 2017-02-10T01:49:08.347 回答