1. 概述

所谓虚拟属性,是指在数据入库之后通过 SQL 表达式对已有的事件属性和用户属性进行二次加工,产生一个新的属性值。

虚拟属性根据表达式中引用到的属性类型分为用户虚拟属性和事件虚拟属性,需要注意的是确定了虚拟用户属性的类型之后只能引用用户表内的属性;虚拟事件属性支持引用「事件属性」和「用户属性」。

本文档所描述的内容属于神策分析的高级使用功能,涉及较多技术细节,适用于对相关功能有经验的用户参考。如果对文档内容有疑惑,请统一咨询客户群内的神策值班同学。

如何使用维度表 > 

2. 创建虚拟属性

2.1. 使用 SQL 确定虚拟属性的值

进入「元数据」-「虚拟属性」后点击「新建」按钮,选择虚拟属性的分类,创建方式选择「使用 SQL 确定虚拟属性的值」并填写好基本信息后,在「SQL 表达式」中填写的 expression 实际上只需要填写对属性的加工的 sql 表达式片段即可快速完成一个虚拟属性的创建,而不需要一个完整的 SQL 表达式。注意事项如下:

  1. 创建虚拟属性时 SQL 表达式最长不能超过 1024 个字符。

  2. events 表中的 time 和 event 属于特殊字段,目前支持对 time 字段二次加工,具体可参考应用场景 5 举例。不支持对 event 字段二次加工提取虚拟属性。

虚拟属性分为两种类型,事件虚拟属性和用户虚拟属性,顾名思义。分别含义请见如下说明:

信息

说明

属性分类

事件虚拟属性:指使用现有的 Event 事件表内的属性进行加工,也可使用 Event 与 用户表的用户属性、Items 表、维度表(在后端通过命令完成关联配置后)后基于此创建新的事件虚拟属性。

用户虚拟属性:指使用现有的 User 用户表中的属性进行二次加工,已完成新的属性与属性值的创建。

属性显示名

属性在使用过程中的显示名称,100 字符以内。

属性名

仅可命名为英文,是事件在系统内的唯一标识。

不能以数值、$ 符号开头,100 字符以内。
注:校验时,属性名大小写不敏感。

数据类型

必填单选:NUMBER、BOOL、STRING、DATETIME、LIST

字典

如果此属性使用了字典,且编辑时修改了虚拟属性的 SQL 规则,则需要在虚拟属性列表上重新上传所需的字典文件。

SQL 表达式

必填,只需要填写对属性的加工的 sql 表达式片段即可,示例可见下文

可用此属性的事件要求



此设置只在选择了属性分类是「事件虚拟属性」后需要设置。(如果是「用户虚拟属性」那么在分析时将所有的事件均可使用此属性进行分析。)

涵盖 SQL 表达式涉及的所有属性的事件,方可使用此虚拟属性。

涵盖至少一个 SQL 表达式中涉及的属性的事件,方可使用此虚拟属性。

2.2. 从普通属性解析获取对应值

注意:SDG 0.12.1 及之后版本才支持此方式,且仅事件虚拟属性支持。

为支持更多业务场景的数据上报,满足客户的实际场景需要,虚拟属性新增支持了对象数组类型,可以将传值为 json 数组的事件属性解析成多个子属性,从而在后续分析过程中使用。

如电商行业购买商品下单时包含的商品名称、商品类别、订单金额等信息,可以通过 json 存储到一个 STRING 类型的普通属性 order_detail 中,后续再解析成对象数组类型的虚拟属性。通过此种方式,仅需上报一条事件解决,而不是拆分到多个事件和属性中,进行多次上报。

"distinct_id": "12345",
"event_name": "pay_order"
"time": 1437280200354,
"order_detail":"[{\"product_name\":\"iPhone 13\", \"product_price\": 5000,\"product_type\": \"手机\", \"cnt\": 3, \"order_price\": 15000},{\"product_name\":\"switch\", \"product_price\": 2000, \"product_type\": \"游戏\",\"cnt\": 1, \"order_price\": 2000},{\"product_name\":\"macbookpro\", \"product_price\": 9000, \"product_type\": \"电脑\", \"cnt\": 1, \"order_price\": 9000},{\"product_name\":\"iphone 14\", \"product_price\": 6000, \"product_type\": \"手机\", \"cnt\": 1, \"order_price\": 6000}]"
CODE


进入「元数据」-「虚拟属性」后点击「新建」按钮,选择事件虚拟属性,创建方式选择「从普通属性解析获取对应值」,并填写以下信息。

信息

说明

属性分类

仅支持事件虚拟属性

属性显示名

属性在使用过程中的显示名称,100 字符以内。

属性名

仅可命名为英文,是事件在系统内的唯一标识。

不能以数值、$ 符号开头,100 字符以内。
注:校验时,属性名大小写不敏感。

数据类型

OBJECTARRAY

解析自事件属性

选择需要解析的普通事件属性,只支持 STRING 类型

字典

此创建方式不支持配置字典

配置子属性

将普通属性传值的 json 解析成子属性。

注意:

  1. 此处配置的子属性名需与解析自事件属性传的 json 内的属性名一致,否则在分析模型中使用时可能会报错。
  2. 子属性的数据类型支持NUMBER、BOOL、STRING、DATETIME、LIST,不支持 OBJECTARRAY。

可用此属性的事件要求

此设置只在选择了属性分类是「事件虚拟属性」后需要设置。(如果是「用户虚拟属性」那么在分析时将所有的事件均可使用此属性进行分析。)

默认选中:仅支持原事件属性所涉及的事件

3. 以下我们提供了几种常见的使用场景:

3.1. 属性计算

【举例 1】

假设埋点的时候埋了两个属性:事件属性(数值类型的属性)「商品标价 commodity_price」和「成交的最终价格 final_price」,当我们想判断商品标价与最终价格的差值时我们可以直接创建一个新的虚拟事件属性「净收入 Net Income」。此时,我们可以使用「加减乘除运算」

SQL 表达式:events.commodity_price - events.final_price

【举例 2】

我们需要基于已有属性,需要对「理财产品的本息总和」进行计算。此时,我们可以使用「幂次函数」。

SQL 表达式:events.capital + events.capital * pow(events.rate_of_interest, events.duration)

3.2. 属性抽取

【举例 1】

例如我们现在有一个事件属性是 $url,希望从 $url 中抽取出 q= 的属性,作为 search_keyword 来进行分析,那么我们可以使用以下表达式创建一个新的虚拟事件属性。

SQL 表达式:parse_url(events.$url, 'QUERY', 'q')

parse_url: 解析 URL,通过指定 URL 中的特定部分返回截取值。可指定要截取的值为 PROTOCOL、HOST、PATH、REF、AUTHORITY、FILE、USERINFO、QUERY。正常我们只需要输入指定的 URL 以及需要截取的部分两个参数, 特殊的当要截取的部分为 QUERY 时, 我们可以输入第三个参数指定 QUERY 键值对中的 key,获取指定参数值。

【举例 2】

例如我们有一个自定义事件属性 error_info_map(字符串类型),上报内容为 JSON 字符串,示例:

error_info_map: '{\"error\": {\"reason\": \"timeout\", \"code\": 3001}}'
JS

希望从这个 JSON 字符串中解析出 reason 的值,作为属性来进行分析,那么我们可以使用以下表达式创建一个新的虚拟属性:

SQL 表达式:GET_JSON_OBJECT(events.error_info_map, '$.error.reason')

GET_JSON_OBJECT:从 JSON 字符串中按照给定的 JSON 选择器解析出 JSON 对象中的值,得到的值为字符串类型。(GET_JSON_OBJECT Impala 官方文档

如果给定的字符串不符合 JSON 格式,或者 JSON 选择器没有匹配到值,则会返回 NULL。

JSON 选择器中支持下列操作符:

  • $:标识根节点
  • .:标识取子节点
  • []:标识数组的取值下标
  • *:标识数组或子节点的通配符

关于 JSON 选择器请参考官方文档

3.3. 属性合并

假设我们在埋点的时候埋了两个属性:item_id 和 item_id_1,但实际上它们是一个含义,希望在使用的时候进行合并,也可以使用虚拟属性功能来定义。

SQL 表达式:coalesce(events.item_id, events.item_id_1)

coalesce 是一个标准 SQL 函数,返回所有参数中第一个非 NULL 的值,这样我们在使用的时候只要使用 new_item_id 来进行分析就可以达到属性合并的目的。

3.4. 联合去重

在神策分析中,我们支持对某个属性进行去重数的计算,但是不直接支持对两个或者更多的属性进行去重。如果有这类需求,也可以使用虚拟属性的方式来实现,即定义一个新的属性,它的值是需要去重的多个属性的组合。

例如,我们想计算不同用户浏览不同商品的去重次数(即一个用户浏览同一个商品不重复计数,但是浏览不同的商品需要计数),那么可以定义一个虚拟属性如下:

SQL 表达式:concat(cast(events.user_id as string), events.product_id)

concat: 联合去重, 把所有string类型的参数连接成一个string类型。

3.5. 高精度小数

默认情况下,神策分析的 NUMBER 类型只支持小数点之后 3 位,如果需要支持高精度类型,可将属性以字符串类型上报给神策,再创建 NUMBER 类型的高精度小数虚拟属性。

将需要支持高精度的内容以字符串的类型来发送给神策分析,以避免精度丢失。此时我们可以通过虚拟属性将此字符串转化为一个高精度类型的虚拟属性。

SQL 表达式:cast(events.big_number as decimal(38,16))

注:不允许上传空字符串,否则自定义查询时无法使用select * ,也无法使用「数据校验」工具

3.6. 校验数据

神策支持创建一个 Bool 类型的属性与正则表达式来校验某个属性值的数据质量。表达式示例如下:

SQL 表达式:cast ( case when regexp_like(users.user_name, '[a-zA-Z0-9._ //-//[//](){}]{1,15}') then 1 else 0 end as bigint)

regexp_like(string source, string pattern[, string options]) : 判断 source 字符串中是否包含以 pattern 为正则表达式的内容

3.7. 时间日期再加工

在用到时间日期函数, 只有 Timestamp 类型可以直接使用 impala 的时间日期函数, 所以如果当 Date/Datetime 类型的属性作为时间日期函数的参数时, 我们需要先使用 EPOCH_TO_TIMESTAMP 函数将属性转换为 Timestamp 类型.

【举例 1】

需要使用每个事件的发生时间,作为分组项来分析数据,或需要在权限中限制某些角色,只可以授权仅可访问「近 N 天的数据」时。那么我们需要基于 event 中的 time 创建一个新的虚拟事件属性,应用在「分析模型」和「角色-数据权限」中。

SQL 表达式:UNIX_TIMESTAMP(events.time)*1000

【举例 2】

默认情况下,神策分析支持天、周、月等时间聚合方式,如果想要其它的时间聚合方式,也可以使用虚拟属性实现。例如,如果想要按照 "周X" 来对数据进行分析,可以从 time 属性中提取出一个 day_of_week 的属性:

SQL 表达式:dayofweek(EPOCH_TO_TIMESTAMP(events.register_time))

dayofweek: 函数求得的数值,1 表示星期天,7 表示星期六,2-6 表示星期一至星期五。类似的,也可以用 extract(hour from time) 表达式来提取时间中的小时部分。

【举例 3】

神策支持使用 users 表中的用户属性提取虚拟属性,比如根据用户属性 Birthday ,得到用户的年龄属性。创建「虚拟用户属性」后,使用此表达式即可。

SQL 表达式:cast (extract(year FROM now()) -extract(year FROM EPOCH_TO_TIMESTAMP(users.Birthday)) as int)

extract: 从 TIMESTAMP 值中截取数值型的时间域,例如年度,月份,日期,小时,分钟,秒/微秒(year,month,day,hour,minute,second,millisecond), 返回时间域的整数值.

注:不支持使用 user 表中的用户属性和维度表、事件表中的事件属性进行关联。

【更多表达式参考】

  • adddate: 在一个 TIMESTAMP 值上加一个给定的天数

    SQL 表达式:adddate(EPOCH_TO_TIMESTAMP(users.birthday), INT/BIGINT days)

  • datediff : 返回两个时间戳间隔天数

    SQL 表达式:datediff(EPOCH_TO_TIMESTAMP(events.enddata), EPOCH_TO_TIMESTAMP(events.startdate))

4. 校验规则与常见错误

  1. 表达式中引用的属性必须存在且已经上报数据

  2. 涉及到两个属性的数值计算时必须保证两个属性数据类型相同

  3. 虚拟用户属性不能引用事件属性

  4. number类型的虚拟属性运算符号两边必须是数字运算数字

  5. 有维度字典的虚拟属性表达式返回值也必须为 bigint, string

  6. 数据类型与返回值必须保持一致
  7. 若创建虚拟属性后,又上报了相同名字的属性, 虚拟属性会失效