Dynamic generate GraphQL schema supports

醉酒当歌 提交于 2020-01-12 05:54:36

问题


Is it possible to dynamically create a GraphQL schema ?

We store the data in mongoDB and there is a possibility of new fields getting added. We do not want any code change to happen for this newly added field in the mongoDB document.

Is there any way we can generate the schema dynamically ?

Schema is defined in code, but for java(schema as pojo), when new attribute is added, you have to update and recompile code, then archive and deploy the jar again. Any way to generate schema by the data instead of pre-define it?

Currently we are using java related projects (graphql-java, graphql-java-annotations) for GraphQL development.


回答1:


You could use graphql-spqr, it allows you auto-generate a schema based on your service classes. In your case, it would look like this:

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

Presumably, you have a service class containing your business logic:

public class PojoService {

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

To expose this service, you'd just do the following:

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

You could then fire a query such as:

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

No need for strange wrappers or custom code of any kind, nor sacrificing type safety. Works with generics, dependency injection, or any other jazz you may have in your project.

Full disclosure: I'm the author of graphql-spqr.




回答2:


After some days' investigation. I found it is hard to generate schema dynamically in Java (or cost is so high).

Well, from another way. I think we can use Map as a compromised way to accomplish that.

  • POJO/Entity

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

    GMap is a customized Map (Because Map/HashMap is a JDK inner class which could not make as GraphQL Schema but only extend).

  • GMap

    public class GMap extends HashMap<String, String> {
    
        @GraphQLField
        public String get(@GraphQLName("key") String key) {
            return super.get(key);
        }
    }
    
  • Retrieve data from Client

    // 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"}}
            ]
        }
    }
    


来源:https://stackoverflow.com/questions/42080536/dynamic-generate-graphql-schema-supports

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!