京东商智_指标服务请求接口统一协议

京东商智_指标服务请求接口统一协议

1.查询接口协议

1.1 maven坐标(调用方引用)

1
2
3
4
5
<dependency>
<groupId>com.jd.bdaa.arch</groupId>
<artifactId>dataservice-provider</artifactId>
<version>1.1.1-RELEASE</version>
</dependency>

1.2 请求入参

接口:com.jd.bdaa.arch.dataservice.UnionDataService

方法:fetchBizData

参数名 类型 必须 描述
header UReqData.Header 请求头
-appkey String 原子服务对调用方的授权key,jdos应用级标识
-uuid String 调用UUID,为了便于日志采集,需满足正则 [a-zA-Z0-9-|_.]+
-context HashMap<String, String> 放置不影响数据结果的参数,如统计、分流、鉴权等服务条件。业务如有诉求,经指标服务配置后可在链路中传递,否则会被拦截。目前可传递字段为:指标类型(不传默认离线):key:INDEX_FREQ value:”REALTIME”/“OFFLINE” (实时/离线)资源场景标识Key(必传):key:RES_APPKEYvalue:例”ge_jdv_boss”备注:当value为”MOCKER“时,代表使用数据探查能力,仅对入参做校验,不实际请求数据库。
body UReqData.Body 请求体
-indicators List 查询指标code列表如需动态传递修饰和函数,请查看本文档第2章
-attributes List 查询维度code列表
-criteria UCriteria 查询条件
– criterions List 筛选过滤查询条件,不支持“或”逻辑运算符
– orders List 排序1、复合指标与同环比类函数指标不支持排序2、定义驱动当前不支持按日期、维度进行排序。
— ascending boolean 升降序,true 正序,false 倒序
— propertyName String 排序属性名
– aliass List (仅需调用方关注)字段别名(节后升级为aliases)
— aliasName String 字段别名
— name String 字段名
– maxResults Integer 查询条数,1~2000
– firstResult Integer 查询数据起始位置 第一条为0
– group List 聚合维度

请求示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
{
"header": {
"appkey": "low_code",
"uuid": "ba09db4a-e34e-4970-b680-3d038230869e",
"context": {
"PIN": "zuoyang10",
"INDEX_FREQ": "OFFLINE",
"RES_APPKEY": "lowcode2374"
}
},
"body": {
"indicators": [
"jdr_sch_traffic_exposure_event_dis_qtty_traffic_plat_expo_di",
"jdr_sch_traffic_click_event_dis_qtty_traffic_plat_click_di",
"jdr_sch_traffic_intr_ord_parent__ord_dis_qtty_jd_traffic_order_path_trade_intr_snapshot"
],
"attributes": [
"saler_bu_id"
],
"criteria": {
"criterions": [
{
"clzType": "InExpression",
"propertyName": "saler_bu_id",
"values": [
"9214"
],
"type": "string",
"op": "in"
},
{
"clzType": "SimpleExpression",
"propertyName": "dt",
"value": "2023-11-08",
"op": ">=",
"type": "string"
},
{
"clzType": "SimpleExpression",
"propertyName": "dt",
"value": "2023-11-08",
"op": "<=",
"type": "string"
},
{
"clzType": "SimpleExpression",
"propertyName": "time_interval",
"value": "BY_DAY",
"op": "=",
"type": "string"
}
],
"orders": [
{
"clzType": "UOrder",
"ascending": false,
"propertyName": "jdr_sch_traffic_exposure_event_dis_qtty_traffic_plat_expo_di"
}
],
"aliass": [],
"maxResults": 1000,
"firstResult": null,
"group": [
"saler_bu_id"
]
},
"dataComparators": null
}
}

过滤条件UCriterion说明:

操作符 类名 备注 示例
=,<>,like,>,<,>=,<= SimpleExpression 单值value { "clzType":"SimpleExpression", "op":">=", "propertyName":"dt", "type":"string", "value":"2021-12-13" }
in InExpression 多值values { "clzType":"InExpression", "op":"in", "propertyName":"bu_id", "type":"string", "values":[ "4517","49747","262016","359305","427324" ] }
notin NotInExpression 多值values { "clzType":"NotInExpression", "op":"notin", "propertyName":"bu_id", "type":"string", "values":[ "4517","49747","262016","359305","427324" ] }
hasAny HasAnyExpression 多值values { "clzType":"HasAnyExpression", "op":"hasAny", "propertyName":"bu_id", "type":"string", "values":[ "4517","49747","262016","359305","427324" ] }
hasAll HasAllExpression 多值values { "clzType":"HasAllExpression", "op":"hasAll", "propertyName":"bu_id", "type":"string", "values":[ "4517","49747","262016","359305","427324" ] }
isnull NullExpression 无值 { "clzType":"NullExpression", "op":"isnull", "propertyName":"bu_id" }
isnotnull NotNullExpression 无值 { "clzType":"NotNullExpression", "op":"isnotnull", "propertyName":"bu_id" }

1.3 返回参数

参数名 类型 必须 描述
header 返回头
-code String 响应码
-desc String 响应描述
body UResData.Body 返回体
-size long 查询总数
-data List<List> 返回数据集合
-metaData UResData.MetaData
– metaIndex Map<String, Integer> 返回数据的索引
– meta List<UResData.Meta> 字段的类型
— di String 返回字段名
— type String 返回字段数据类型
-errors List 查询失败的指标对应的错误信息
-code String 错误码
-desc String 描述
-serviceId Long 原子服务ID
-indicators Set 原子服务相关的指标
-dims Set code为2003时为查询时忽略的原子服务相关的维度

返回示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
"header": {
"code": "200",
"desc": "成功",
"values": "CacheDataStableInfo###{\"jdr_sch_traffic_intr_ord_purchase__user_dis_qtty_jd_traffic_order_path_user_valid_steady_cate_1_new_user\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_purchase__user_cnt_jd_traffic_order_path_trade_valid_snapshot\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_purchase__user_dis_qtty_jd_traffic_order_path_trade_deal_snapshot\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_sku_piece_jd_traffic_order_path_trade_deal_snapshot\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_purchase__user_dis_qtty_jd_traffic_order_path_user_valid_steady_cate_2_new_user\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_ord_amt_jd_traffic_order_path_trade_deal_snapshot\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_exposure_event_dis_qtty_traffic_plat_expo_di\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_parent__ord_dis_qtty_jd_traffic_order_path_trade_intr_snapshot\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_purchase__user_dis_qtty_jd_traffic_order_path_user_valid_steady_cate_3_new_user\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_parent__ord_dis_qtty_jd_traffic_order_path_trade_valid_snapshot\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_parent__ord_dis_qtty_jd_traffic_order_path_trade_deal_snapshot\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_click_event_dis_qtty_traffic_plat_click_di\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200},\"jdr_sch_traffic_intr_ord_purchase__user_dis_qtty_jd_traffic_order_path_user_valid_steady_buid_new_user\":{\"tableList\":[\"adm_jdr_sch_d14_mkt_gold_process_tying_expo_d\"],\"stableTime\":1200}}###StableInfoEnd;"
},
"body": {
"size": 1000,
"data": [
[
"9214",
3334202,
89452
]
],
"metaData": {
"metaIndex": {
"saler_bu_id": 0,
"jdr_sch_traffic_exposure_event_dis_qtty_traffic_plat_expo_di": 1,
"jdr_sch_traffic_click_event_dis_qtty_traffic_plat_click_di": 2
},
"meta": [
{
"di": "saler_bu_id",
"type": "java.lang.String"
},
{
"di": "jdr_sch_traffic_exposure_event_dis_qtty_traffic_plat_expo_di",
"type": "long"
},
{
"di": "jdr_sch_traffic_click_event_dis_qtty_traffic_plat_click_di",
"type": "long"
}
]
}
},
"errors": []
}

统一错误码:

编码区间 code desc value 说明
2开头 返回数据类 200 successful successful 成功
2000 part fail PV,UV 失败指标例如”PV””,”UV”
2001 rate limit PV,UV 限流指标例如”PV””,”UV”
2002 circuit breaker PV,UV 降级指标例如 “PV”,”UV”
2003 criteria ignored PV,UV 忽略条件后返回指标数据
2004 Exceed the limit of downloaded lines 超出40W下载行数上限
1开头 用户传参类 1001 indicator exception PV 指标传参异常
1002 attributes exception cate_1 维度传参异常
1003 time exception 2021-10-10 时间格式传参异常
1004 group by exception cate_1 聚合传参异常
1005 order by exception 排序传参异常
1006 criteria is not support criteria传参不支持
1007 required parameter is null exception 必传参数为空
1008 page parameter exception 分页参数异常
3开头 权限类 3001 no permission to call this api API 无权限
3002 app is not in whitelist app 无权限
3003 data auth validate error 无指标或维度值权限
4开头 系统类 4001 system error occurred 系统异常
4002 query time out 查询超时
5开头 数据服务类 5001 physical service error occurred 指标服务异常
5002 physical service do not exist 指标服务不存在

2.indicators指标扩展修饰&函数

修饰就是一个定义好的绑定一个维度字段的case when条件。

采用 metric_a@tob&filter_jx#yoy?rate 这种形式的调用方式,说明如下:

1、@表示修饰,@后面可以有多个修饰,并以&进行分割

2、#表示指标自身的函数能力,函数可附带一个参数,由 ? 连接。不同类函数(至今类、同环比类)可以有多个,以&分割。

3、@#顺序为@在前#在后

4、指标后函数最多支持5个,修饰最多支持10个

具体指标可支持哪些修饰和函数,见指标服务平台的指标详情页。通用的函数枚举值如下:

函数名称 函数编码 备注
同比 yoy (Year(x)-Year(x-1))/Year(x-1)
同比618 yoy_618 (Year(x)-Year618(x-1))/Year618(x-1)
同比1111 yoy_1111 (Year(x)-Year1111(x-1))/Year1111(x-1)
4小时错位同比 yoy_4h 取去年同期并向后错4小时,比如晚8比去年同期12点
环比 mom (Day(x)-Day(x-1))/Day(x-1)
周环比 mom_week Week(x)-Week(x-1))/Week(x-1)需要注意,如果Week(x)是非整周时,例如本周尚只有3天数据,环比上周时,上周也取前3天数据
月环比 mom_month (Month(x)-Month(x-1))/Month(x-1)需要注意,如果Month(x)是非完整月时,例如本月只过了3天,环比上月,上月也取前3天数据。另外,如果本月有31天,上月只有28天,当本月到了29天时,环比上月环比上月整月。如果是小月对比大月,如2月对比1月,则也是对比1月整月
近14日环比 mom_14day (Recent14Days(x)-Recent14Days(x-1))/Recent14Days(x-1)环比的固定周期是对比上期的时间间隔,具体对比的时间段由时间入参请求确认,按照开始时间往前推14天
近30日环比 mom_30day (Recent30Days(x)-Recent30Days(x-1))/Recent30Days(x-1)环比的固定周期是对比上期的时间间隔,具体对比的时间段由时间入参请求确认,按照开始时间往前推30天
农历同比 yoy_luc 取农历去年的同期,(Yearluc(x)-Yearluc(x-1))/Yearluc(x-1)

指标服务扩展参数新增“#同环比参数?计算公式”,用来请求指定指标的同环比。支持的同环比参数如上表,计算公式有比率(ratio)、比值(rate)、上期值(period)。举例说明:

  • 当指定指标类型为比值时,如“成交金额”,扩展参数入参为:

    • 同比:#yoy?rate
    • 环比:#mom?rate
  • 当指定指标类型为比率时,如“转化率”,扩展参数入参为:

    • 同比 #yoy?ratio
    • 环比 #mom?ratio

定义驱动提供的配置化原子服务额外支持如下函数:

函数英文名 函数中文名
mtd 月至今
wtd 周至今
qtd 季至今
ytd 年至今
ld7 近7天
ld30 近30天
lrd 最近就绪时间

3.入参解析

入参中UCriterion过滤条件的拆解和解析比较有抽象价值。

构建了一个过滤条件抽象类AbstractUCriterionConverter,然后每种过滤类型有一个实现类,如InExpression:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Component
@Slf4j
public class InExpressionConverter extends AbstractUCriterionConverter<InExpression> {

public static final Logger LOGGER = LoggerFactory.getLogger(InExpressionConverter.class);

public static final DriveMathOperatorEnum opEnum = DriveMathOperatorEnum.IN;

@Autowired
public InExpressionConverter(UCriterionConverterManager manager, UnifyDimDefService unifyDimDefService) {
super(InExpression.class, manager, unifyDimDefService);
}

@Override
public DriveFilterBO convert(InExpression criterion) {
DriveFilterBO filterBO = new DriveFilterBO();
filterBO.setMathOp(opEnum);
Long dimId = getDimIdByName(criterion.getPropertyName());
filterBO.setDimensionDefId(dimId);
List<String> valueList = new ArrayList<>();
checkValue(criterion);
Object[] values = criterion.getValues();
for (Object item : values) {
valueList.add(String.valueOf(item));
}
filterBO.setValueList(valueList);
return filterBO;
}

/**
* 对筛选值进行校验
*/
private void checkValue(InExpression criterion) {
if (Objects.isNull(criterion.getValues()) || criterion.getValues().length == 0) {
UmpUtil.alarmUser(UmpUserAlarmType.FILTER_EXCEPTION.geErrorMsg(), UmpUserAlarmType.FILTER_EXCEPTION.getInfo());
throw new UserException("筛选值为空!");
}
}
}

其中的运算符枚举类型如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public enum DriveMathOperatorEnum {
UNKNOWN("", 0),
EQUAL("=", 2),
NOT_EQUAL("<>", 2),
LARGE(">", 2),
LESS("<", 2),
LARGE_EQUAL(">=", 2),
LESS_EQUAL("<=", 2),
LIKE("like", 2),
NOT_LIKE("not like", 2),
BETWEEN("between", 2),
IN("in", 2),
NOT_IN("not in", 2),
ISNULL("is null", 2),
ISNOTNULL("is not null", 2),
HAS_ANY("hasAny", 2),
HAS_ALL("hasAll", 2);

private String operator;
private int priority;

/**
* 枚举名称 map
*/
private static final Map<String, DriveMathOperatorEnum> NAME_MAP;

static {
NAME_MAP = Arrays.stream(values())
.collect(toMap(DriveMathOperatorEnum::getOperator, identity()));

}

private DriveMathOperatorEnum(String operator, int priority) {
this.operator = operator;
this.priority = priority;
}

public String getOperator() {
return this.operator;
}

public int getPriority() {
return this.priority;
}

public static DriveMathOperatorEnum of(String name) {
return NAME_MAP.getOrDefault(name, UNKNOWN);
}
}