Coder Social home page Coder Social logo

graphql-calculator / graphql-calculator Goto Github PK

View Code? Open in Web Editor NEW
104.0 104.0 16.0 10.98 MB

A lightweight graphql calculation engine, which is used to alter execution behavior of query.

License: Apache License 2.0

Java 93.04% Groovy 6.96%
graphql graphql-directive graphql-java java

graphql-calculator's Introduction

graphql-calculator

Build and Publish Latest Release

📖 English Documentation | 📖 中文文档


GraphQL Calculator is a lightweight graphql query calculation engine. Based on directive, graphql-calculator provide graphql query with the ability of field transform, field skip and orchestration.

Features

The name and semantics of directives are inspired from the java.util.stream.Stream, so they are easy to understand and use.

The argument of directive must be static string value. query variables can't be used, because variable will make the semantics and validity of query ambiguous.

  • processing field value: processing the fetched values and transform them to a new value;
  • processing list field: the collection can be easily filtered, sorted and de-duplicated;
  • processing field argument: transform field arguments to new values before use them to fetch the field value, and the arguments of transform operation can be query variables and the fetched value of other fields;
  • flow control: provide the extended version of @skip and @include, and the value of expression decided whether skip the operation of field-fetched;
  • data orchestration: a field's fetched value will always could be the arguments of other fields.

Getting Started

1. Add dependency

implementation group: 'com.graphql-java-calculator', name: 'graphql-java-calculator', version: {version}

2. Wrap graphql engine

2.1 Create GraphQLSource

Create GraphQLSource by DefaultGraphQLSourceBuilder, which including wrapped graphql schema and graphql execution engine GraphQL.

You can config script engine through Config, and the default script engine is [aviatorscript](https://github.com/killme2008/aviatorscript.

2.2 Validation

Validate the query by Validator, which including graphql syntax validation.

It is recommend to create PreparsedDocumentProvider by implementing CalculatorDocumentCachedProvider.

More details in Example.java and examples.graphql

Note: If customized async DataFetcher is used, then make it implements AsyncDataFetcherInterface, and return the wrapped DataFetcher and the Executor used in async DataFetcher by override method. If graphql.Schema.Asyncdatafetcher of 'graphql-java' is used, this operation can be ignored.

Feature Showcase

There are all the definitions of calculation directives:

# determine whether the field would be skipped by expression, taking query variable as script arguments
directive @skipBy(predicate: String!) on FIELD | INLINE_FRAGMENT | FRAGMENT_SPREAD

# determine whether the field would be queried by expression, taking query variable as script arguments.
directive @includeBy(predicate: String!) on FIELD | INLINE_FRAGMENT | FRAGMENT_SPREAD

# reset the annotated field by '@mock', just work for primitive type. it's easily replaced by '@map(expression)'
directive @mock(value: String!) on FIELD

# filter the list by predicate
directive @filter(predicate: String!) on FIELD

# returns a list consisting of the distinct elements of the annotated list
directive @distinct(comparator:String) on FIELD

# sort the list by specified key
directive @sort(key: String!,reversed: Boolean = false) on FIELD

# sort the list by expression result
directive @sortBy(comparator: String!, reversed: Boolean = false) on FIELD

# transform the field value by expression
directive @map(mapper:String!, dependencySources:[String!]) on FIELD

# hold the fetched value which can be acquired by calculation directives, the name is unique in query.
directive @fetchSource(name: String!, sourceConvert:String) on FIELD

# transform the argument by expression
directive @argumentTransform(argumentName:String!, operateType:ParamTransformType, expression:String, dependencySources:[String!]) repeatable on FIELD
enum ParamTransformType{
    MAP
    FILTER
    LIST_MAP
}

Assume we have type definition as in examples.graphql, Here are some examples on how to use GraphQL Calculator on graphql query.

query basicMapValue($userIds:[Int]){
    userInfoList(userIds:$userIds)
    {
        id
        age
        firstName
        lastName
        fullName: stringHolder @map(mapper: "firstName + lastName")
    }
}

query filterUserByAge($userId:[Int]){
    userInfoList(userIds: $userId)
    @filter(predicate: "age>=18")
    {
        userId
        age
        firstName
        lastName
    }
}

query passFetchedValueToAnotherFieldArgument($itemIds:[Int]){
    commodity{
        itemList(itemIds: $itemIds){
            # save sellerId as List<Long> with unique name "sellerIdList"
            sellerId @fetchSource(name: "sellerIdList")
            name
            saleAmount
            salePrice
        }
    }

    consumer{
        userInfoList(userIds: 1)
        # transform the argument of "userInfoList" named "userIds" according to expression "sellerIdList" and expression argument, 
        # which mean replace userIds value by source named "sellerIdList"
        @argumentTransform(argumentName: "userIds", 
            operateType: MAP, 
            expression: "sellerIdList", 
            dependencySources: ["sellerIdList"]
        ){
            userId
            name
            age
        }
    }
}

License

This project is released under version 2.0 of the Apache License.

graphql-calculator's People

Contributors

dugenkui03 avatar wsamuel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

graphql-calculator's Issues

graphql-java update 22.0

graphal-java已经升级22.0,提供了大量的性能优化,作为计算的组件是否有更新计划

support @includeBy

directive @includeBy(predicate: String!, dependencySources:[String!]) on FIELD

升级graphql-java核心库

graphql-java version-17经过3个小版本的迭代已经趋于稳定,graphql-calculator对graphql-java进行升级:

  1. 常规升级;
  2. 17版本为GraphQL类提供了getter方法,并且该对象有transform方法,考虑是否可以直接将GraphQL作为入参、将其转换为具有计算能力的GraphQL对象,简化用户使用GraphQl Calculator的成本;
  3. 内置AsyncDataFetcher中添加了getter方法,README中弱化AsyncDataFetcherInterface说明,将其作为注意事项即可;

[New Feature] @partition(size: Int) on ARGUMENT_DEFINITION

background

Query want to get too many element by array argument.

query getTooManyItemByIds(itemIds:[Int]){
     # partition the itemIdList by particular size
      itemList(itemIds:$itemIds){
             id
             price
      }
} 

definition

directive @partition(size: Int) on ARGUMENT_DEFINITION

usage case

Type Query{
     itemList(itemIds @partition(size:20)): [Item]
}

DataFetcherDefinition.isAsyncFetcher 永远为false

public DataFetcherDefinition build() { return new DataFetcherDefinition( isAsyncFetcher, isGraphqlAsyncFetcher, isCalculatorAsyncFetcher, originalFetcher, wrappedDataFetcher, actionFetcher, executor ); }

calculator.common.GraphQLUtil#getDataFetcherDefinition
该方法并为对isAsyncFetcher赋值,所以一直为false

过滤、排序指令

解析结果比获取结果语义更加明确,评估是否可以放到解析阶段,而非获取阶段。

  1. 过滤 Array;
  2. 为 HashSet 这种无序集合排序;
  3. 如果过滤/排序操作耗时较长,是否有病发问题、即异步任务没有执行完成、没有过滤掉的结果/没有排序好的列表已经返回给其他操作使用。

自定义指令

提供注册自定义指令的机制,可以指定指令如下信息:

  1. 名称

    • 约束命名;
  2. 类型:修改运行时行为、校验;

    • 校验:统一异常接口;
    • 修改运行时行为:可能要有很多个接口,不同阶段的运行时行为有不同的接口;
  3. 位置/类型系统指令还是查询指令

函数"范本"

业务中的计算可大致归类如下:

  • 基本逻辑计算:数值计算、字符串处理;
  • 集合计算:列表过滤、列表大小、列表元素转换、找出集合最大/最小值、去重、集合分组等;

对于这种典型的计算,是否应该写一套“范本函数”,类似于 aviator函数库+其他补充,作为其他函数引擎的函数实现示范。

将请求变量作为表达式变量

  1. 执行逻辑:如果表达式变量前缀为$,则从查询变量取值;
  2. 表达式校验:如果表达式变量前缀为$,则查看是否有该查询变量。

示例:

query useVariableAsDirectiveArgument($userId:Int){
    consumer{
        userInfo(userId: $userId){
            # $前缀的变量为请求变量值
            userId: age @map(mapper: "$userId")
            name
        }
    }
}

关闭#28

Wanted: 欢迎使用该组件的用户在此注册

诚挚感谢每位持续关注并使用GraphQL Calculator的朋友,我将会持续投入、力图将GraphQL Calculator做的更好。为了更好的聆听用户的声音,吸引更多的人使用和参与,期待您在此提交您的使用信息,这也是对我的一种鼓励。

评论内容包括:

  • 您所在公司、学校或组织的名称;
  • 您所在公司、学校或组织的官方网址;
  • 您的联系方式:邮箱、微博、微信 (至少一个)。

uniqueJoin

类似于mysql中的join,将[ItemInfo] 和[SellerInfo] 按照货主id进行匹配后、合并成List在页面进行展示是常见的业务处理逻辑。

使用 @Map 和 @fetchSource进行处理会使得其中一个类型每个需要被合并的字段都需要单独进行处理,字段较多或者匹配逻辑复杂时会是的查询dsl的可读性变差。

待定方案

@uniqueJoin(key:String, mergeInfo:[JoinInfo])

input JoinInfo{ 
   sourceName:String, 
   sourceKey:String
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.