首页 文章

动态生成GraphQL架构支持

提问于
浏览
2

是否有可能 dynamically 创建GraphQL架构?

我们将数据存储在mongoDB中,并且可能会添加新字段 . 我们不希望在mongoDB文档中对此新添加的字段进行任何代码更改 .

我们有什么方法可以动态生成架构吗?

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

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

2 回答

  • 0

    您可以使用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
            } } }
    

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

    Full disclosure: 我是graphql-spqr的作者 .

  • 4

    经过几天的调查 . 我发现很难用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而只是扩展) .

    • GMap
    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"}}
            ]
        }
    }
    

相关问题