GQL

GQL

作者:王书硕


普通的gql

最简单的,直接查一个对象的全部数据

{
  BudgetAccount{
    id
    name
    accountType {
      id
      name
    }
  }
}

加一点查询条件

{
  BudgetAccount(criteriaStr:"name in ('1','2','3')"){
    id
    name
    accountType {
      id
      name
    }
  }
}

这个会查到name为1、2、3的多条数据

高级的gql

上面只能查到一个表的数据及其关联的外键,子表的数据。下面来搞一个子查询。

因为有的时候,后端的模型中,没有包含我们需要的子表,只能我们自己构建

{
  BudgetAccount(criteriaStr:""){
    a: exprField(expr:"()")
    b: exprField(expr:"()")
  }
}

其中a:是个模型上的一个字段起别名,exprField是一个可以扩展的额外字段,利用这两个就可以做成子查询了。

举个例子。对于预算指标,复合指标有若干个子指标,但是直接通过BudgetIndicator模型获取不到它们。就可以这样做

{
  BudgetIndicator(criteriaStr:"isComposite=true"){
    id
    isComposite
    child: exprField(expr:"(select string_agg(CONCAT_WS(',',childIndicator.id,childIndicator.name),';')  from BudgetIndicatorComposition where parentIndicatorId=m.id)")
  }
}

这里使用了两个sql函数把多条记录、多个字段组合成了一个字符串。拿到数据后前端经过简单的split转化就可以拿到json对象了。

常用的sql函数

string_agg: 如果查出来有多条结果,会将它们拼装为一个字符串
例子:string_agg(object.name, ', ')

coalesce:如果alias存在则取alias,不存在取name
例子:string_agg((coalesce(indicator.alias, indicator.name)), ', ')

concat_ws:拼装一条记录的多个字段为一个字段
例子:string_agg(CONCAT_WS(',',childIndicator.id,childIndicator.name),';')

DataLoader

const settingDataLoader = new DataLoader(
  EN_Setting, // 要查的业务对象
  ['values.value'], // 要查的字段
  {
    criteriaStr: `key='${accountingBook}'`, // 查询条件
    sorts:[{{name:"code", isDesending:false}] // 排序
  } as QueryOptions
);

const ret = await settingDataLoader.query();

不适用DataLoader,直接使用gql

import client from '@client';
const fetchControlBalance = async (criteriaStr: string, dimensionField: string[]) => {
  const res = await client.query<{ data: Array<IInvoiceType> }>({
    query: `
    {
      data: BudgetControlBalance(criteriaStr: "${criteriaStr}"){
        id
      }
    }
    `,
  });
  return res.data.data
};

Go怎么查GQL

func GetFieldMapping(c context.TrekContext, billClassId string) []Mapping {
	queryString := `{
  BudgetDimensionFieldMapping(criteriaStr:"billClassId = '{{.billClassId}}' and dimensionId = 'FinancialOrg'"){
    mappingToWhereId mappingField
}
}`
	query := graphql.GraphqlTemplate(queryString, map[string]string{
		"billClassId": billClassId,
	})

	data := map[string]interface{}{
		"query": query,
	}

	var dataJson FieldMappingRes

	context.HttpRequest.DoHTTPPost(c, urls.AppGraphQL, &context.HTTPOptions{
		BindBody:    &dataJson,
		ParamStruct: &data,
	})
	return dataJson.Data.BudgetDimensionFieldMapping
}

type Mapping struct {
	MappingToWhereId string `json:"mappingToWhereId"`
	MappingField     string `json:"mappingField"`
}

type FieldMappingRes struct {
	Data struct {
		BudgetDimensionFieldMapping []Mapping `json:"BudgetDimensionFieldMapping"`
	} `json:"data"`
	Errors []interface{} `json:"errors"`
}
  1. queryString定义语句的模板,其中可以包含一些模板变量
  2. GraphqlTemplate将模板变量引用到模板
  3. 用DoHTTPPost发起请求