文章出处(https://developer.sjtu.edu.cn/graphql/overview.html)
GraphQL语法说明
#说明
GraphQL是一个用于API的查询语言,数据资源API服务通过接收GraphQL查询,并验证和执行。接收到的查询首先会被检查确保它只引用了已定义的类型和字段,然后运行指定的解析函数来生成结果。
#GraphQL语言结构
{ tm_class(first: 1, offset:10, filter:{name:{eq : "123"}}){ num name id } }
以上面示例,GraphQL有三部分组成
- 第一部分type类型,在数据资源API中其实际为接口的名称 //tm_class
- 第二部分查询条件,在数据数据资源API中内设3个关键字(first、offset、filter) //(first: 1, offset:10, filter:{name:{eq : "123"}})
- 第三部分查询字段,表示用户本次API查询需要获取的数据字段,查询字段是受权限保护,对于用户无权限访问的字段,一律返回空值;用户发送查询请求时,可去除未申请的字段;如果希望对返回的字段进行重命名可通过(重命名:字段名 username:name) //{ num name id }
#GraphQL查询条件
GraphQL语句中过滤条件内设三个关键字(first、offset、filter);在filter中配置查询条件,filter的value是一个map集合,可以是一个嵌套的key&value。
filter查询过滤
- filter其本质数据结构是一个嵌套的键值对,基本语法: {字段名: {查询关键字: 查询值}}
- 在一个键值对中不能出现相同的key,例如(name:{eq : "123", eq: "231"}),这是不合法的,可以直接通过in,not in的方式来实现
- filter中不是所有字段都可作为查询参数,根据每个API接口提供的查询参数进行相应配置
- 需要特别注意,在filter中如果查询值是字符串,需对相应的双引号转义
//查询语句事例, filter中的双引号需转义
public static String selectStatement = "{ tm_class(first: 1, offset:10, filter:{name:{eq : \"123\"}}){ num name id } }";
public static void main(String[] args) {
Map<String, String> bodyMap = new HashMap<String, String>();
bodyMap.put("query", selectStatement);
String response = null;
try {
response = HttpUtils.get(apiEndPoint, new Gson().toJson(bodyMap), "");
}catch (Exception e) {
e.printStackTrace();
}
}
filter查询关键字
关键字 | 符号 | 解释 | 案例 |
---|---|---|---|
eq | == | 等号 | {userid:{eq : "123"}} |
ne | != | 不等于 | {userid:{ne: "123"}} |
ge | >= | 大于等于 | {userid:{ge: "123"}} |
gt | > | 大于 | {userid:{gt: "123"}} |
le | <= | 小于等于 | {userid:{le: "123"}} |
lt | < | 小于 | {userid:{lt: "123"}} |
like | like | sql中like语法 | {userid:{like: "%123%"}} |
nlike | nlike | sql中not like语法 | {userid:{nlike: "%123%"}} |
in | in | sql中的in语法 多个值之间用逗号隔开 查询值用[]包围 |
{userid:{in: ["123", "321"]}} |
nin | not in | sql中的not in语法 多个值之间用逗号隔开 查询值用[]包围 |
{userid:{nin: ["123", "321"]}} |
nil | null | sql中is null语法 查询值用”“ |
{userid:{nil: ""]}} |
notnull | not null | sql中is not null语法 查询值用”“ |
{userid:{notnull: ""]}} |
filter查询逻辑符(AND/OR)
- filter中也支持AND和OR的逻辑符号,优先级和数据库sql查询一致。默认缺省值为AND。 通过嵌套逻辑符号,可以实现十分复杂的过滤查询。
下面通过一些常用的配置,基本可以了解filter的相应的写法
- 缺省查询条件
# sql中查询 (name="123" and age > 1)转换成graphql的filter写法
filter:{name:{eq : \"123\"}, age:{gt : 1}}
# 上面的filter和下面filter语句的语义是一致的
filter:{and:{name:{eq : \"123\"}, age:{gt : 1}}}
- 实现sql中between...and...的
# sql中查询 (name="123" and age between 1 and 10)转换成graphql的filter写法
filter:{and:{name:{eq : \"123\"}, age:{ge : 1, le : 10}}}
- 简单的or查询
#sql中查询(name is null or name="123")转换成graphql的filter写法
filter:{or:{name:{nil : \"\", eq : \"123\"}}}
#sql中查询(name = "123" or age > 10)
filter:{or:{name : {eq : \"123\"}, age: {lt: 10}}}
- AND语句中嵌套OR (复杂的条件语句不能使用缺省条件)
#sql中查询(age > 10 and (name is null or name like "王%"))转换成graphql的filter写法
filter:{and: {age: {gt : 10}, or:{name : {nil: \"\", like: \"王%\"}}}}
- OR语句中嵌套And (复杂的条件语句不能使用缺省条件)
#sql中查询(age > 10 or (name is not null and name like "王%"))转换成graphql的filter写法
filter:{or: {age : {gt : 10}, and: {name : {notnull : \"\", like : \"王%\"}}}}
#分页查询关键字
过滤条件3大关键字(offset, first, filter), offset和first就是用来指定分页的参数。对于没有指定分页参数的,默认最多返回500条数据。
- first:第一条数据开始的位置, first最小值为1
- offset: 偏移量,一次查询获取最大多少数据
- 假设一次查询10条数据,第一次为(first:1, offset: 10), 则第二次为(first:11, offset:10)。即第二次查询first= (前一次first + 前一次offset)
- 分页查询实例
#第一次查询10条数据
{ tm_class(first: 1, offset:20){ num name id } }
#则第二次查询10条数据
{ tm_class(first: 21, offset:20){ num name id } }
#GraphQL构造示例
示例 graphql语句嵌入查询条件
public class GraphqlFilterHandler {
public final static String FILTER_KEYWORD = "filter";
public final static String PAGE_FIRST_KEYWORD = "first";
public final static String PAGE_OFFSET_KEYWORD = "offset";
/**
* @Title: GraphqlStatementAddFilterCriteria
* @Description: 嵌入的过滤条件
* @param: @param graphqlStatement : graphql查询语句
* @param: @param criteriaEntities :查询条件
* @param: @return
* @return: String
* @throws
*/
public static String GraphqlStatementAddFilterCriteria(String graphqlStatement, CriteriaEntity...criteriaEntities ) {
String filterStatement = buildCriteria(graphqlStatement, criteriaEntities);
graphqlStatement = addFilterCriteria(graphqlStatement, filterStatement);
return graphqlStatement;
}
/**
*
* @Title: GraphqlStatementAddFilterCriteria
* @Description: 附带 分页参数
* @param: @param graphqlStatement
* @param: @param pagePara
* @param: @return
* @return: String
* @throws
*/
public static String GraphqlStatementAddFilterCriteria(String graphqlStatement, int first,
int offset, CriteriaEntity...criteriaEntities) {
String pageFirstStatement = PAGE_FIRST_KEYWORD + " : " +first;
String pageOffsetStatement = PAGE_OFFSET_KEYWORD + " : " + offset;
String filterStatement = buildCriteria(graphqlStatement, criteriaEntities);
if(StringUtils.isEmpty(filterStatement)) {
filterStatement = "(" + pageFirstStatement + ", " + pageOffsetStatement + ")";
}else {
int pos = filterStatement.indexOf(")");
String suffix = filterStatement.substring(0, pos);
filterStatement = suffix + ", " + pageFirstStatement + ", " + pageOffsetStatement + ")";
}
graphqlStatement = addFilterCriteria(graphqlStatement, filterStatement);
return graphqlStatement;
}
private static String buildCriteria(String graphqlStatement, CriteriaEntity...criteriaEntities) {
String filterStatement = "";
Map<String, Object> filterMap = new HashMap<String, Object>();
for(CriteriaEntity criteriaEntity : criteriaEntities) {
QueryFilterEnum filterEnum = criteriaEntity.getQueryFilterEnum();
Map<String, Object> map = filterEnum.criteriaStatement(criteriaEntity);
filterMap.put(criteriaEntity.getFieldName(), map);
}
if(filterMap.size() == 0) {
if(graphqlStatement