让决策更智能
新一代智能数据分析平台

行权限使用案例分享

观小远发表于:2021年03月16日 19:05:11更新于:2021年03月16日 19:38:56


案例一:


       用户属性里有大区、城市,总公司员工大区属性里有值,可能有一个或者多个值(例如华东),城市为空,可以查看自己所在大区的所有数据,子公司员工大区为空,城市可能有一个或者多个值(例如上海,杭州),只可以查看自己管辖城市下的数据。总公司和子公司员工同属于一个大的用户组。
      非直连(非加速)数据集,字段有大区、省份、城市,大区可以精确匹配,但是省份、城市是全称,例如上海市、杭州市、内蒙古自治区,跟用户属性不能精确匹配。

行权限写法:

case when [CURRENT_USER.大区]<> '' then array_contains(split([CURRENT_USER.大区],','),[大区]) 
when [CURRENT_USER.大区]= '' and [CURRENT_USER.城市]<> '' then array_contains(split([CURRENT_USER.城市],','),regexp_replace([城市],'市|地区','')) or array_contains(split([CURRENT_USER.城市],','),replace([省份],'市')) 
else null end

001605097a001c3d8f3a8fb81526860逻辑:
1. case when [CURRENT_USER.大区]<> '' then array_contains(split([CURRENT_USER.大区],','),[大区])  ——判断总公司用户,匹配“大区”字段;
2. when [CURRENT_USER.大区]= '' and [CURRENT_USER.城市]<> '' ——判断子公司用户;
3. then array_contains(split([CURRENT_USER.城市],','),regexp_replace([城市],'市|地区','')) ——把城市字段去掉“市“或者“地区”再进行匹配,如果某些城市名字里带有其他后缀例如”自治州“,可以嵌套使用 replace 函数或者使用正则表达式 regexp_replace来去掉后缀;
4. or array_contains(split([CURRENT_USER.城市],','),replace([省份],’市’))  ——直辖市城市名如果在省份里,需要匹配”省份“。

Note:如果用户属性是字符串单值,可以直接使用 [CURRENT_USER.大区]=[大区] 这样的精确匹配,和 [城市] like concat(‘%’,[CURRENT_USER.城市],‘%’) 这样的模糊匹配。但是多值的情况下要逐个匹配,需要把该属性值拆分开变成数组,分隔符使用用户属性里设置的分隔符,所以需要用array_contains(split()) 函数,同时也完全适应单值的情况; 不过数组不适用模糊匹配,不能用 like, 所以需要对数据集字段做处理。位置和长度都一样的情况可以使用 substr 来代替 replace,例如 array_contains(split([CURRENT_USER.城市],','),substr([城市],1,2)) 。

上述场景,数据集转换为高性能数据集(加速数据集)后,原来的 spark SQL 函数将不再适用,需要替换为对应的clickhouse SQL函数。上述行权限需要转换为如下写法,同理,Clickhouse直连数据集也适用如下写法:

case when [CURRENT_USER.大区]<> '' then has(splitByChar(',',[CURRENT_USER.大区]),[大区]) 
when [CURRENT_USER.大区]='' and [CURRENT_USER.城市]<>''then has(splitByChar(',',[CURRENT_USER.城市]),replaceRegexpOne([城市],'市|地区','')) or has(splitByChar(',',[CURRENT_USER.城市]),replaceOne([省份],'市','')) 
else null end

用户属性:城市——上海,杭州,喀什

实现效果:001605096f4c83434c12861e243d8ab



案例二:


       用户属性城市为多值,每个用户至少有一个城市,一般情况下用户可以看自己属性里所有城市的数据。但是有个别数据集只允许用户看自己所在地城市的数据,所在地城市就是城市属性里的第一个值,所以需要数据集字段只匹配第一个城市。
      案例一同一数据集,非直连(非加速)数据集,省份、城市是全称,例如上海市、杭州市、内蒙古自治区,跟用户属性不能精确匹配。普通城市名需要去掉“市”“地区”之类后缀,直辖市需要去掉“市”再跟省份匹配。

行权限写法一:

array_position(split([CURRENT_USER.城市],','),regexp_replace([城市],'市|地区',''))=1 or array_position(split([CURRENT_USER.城市],','),replace([省份],'市'))=1

 
逻辑:用 split([CURRENT_USER.城市],',') 把城市拆分成数组,array_position()=1 确保提取的是数组中第一个元素。即使用户属性是单值也适用。

行权限写法二:

case when INSTR([CURRENT_USER.城市],',')>1 then SUBSTR([CURRENT_USER.城市],0,INSTR([CURRENT_USER.城市],',')-1) in (regexp_replace([城市],'市|地区',''),replace([省份],'市')) 
else [CURRENT_USER.城市] in (regexp_replace([城市],'市|地区',''),replace([省份],'市')) end


逻辑:把用户属性“城市”按照字符串处理,用 case when 判断是单值还是多值,多值情况截取第一个分隔符前的城市名,单值直接匹配城市或者省份。

加速数据集,Clickhouse直连数据集逻辑同上。
写法一:

arrayElement(splitByChar(',',[CURRENT_USER.城市]),1) = replaceOne([省份],'市','') or arrayElement(splitByChar(',',[CURRENT_USER.城市]),1) =replaceRegexpOne([城市],'市|地区','')


写法二:

case when position([CURRENT_USER.城市],',')>1 then substring([CURRENT_USER.城市],1,position([CURRENT_USER.城市],',')-1) = replaceRegexpOne([城市],'市|地区','') or substring([CURRENT_USER.城市],1,position([CURRENT_USER.城市],',')-1) = replaceOne([省份],'市','') 
else [CURRENT_USER.城市]= replaceRegexpOne([城市],'市|地区','') or [CURRENT_USER.城市]= replaceOne([省份],'市','') end

用户属性:城市——上海,杭州,喀什

实现效果:001605097386d9cba6fa9cc4f51743f



    您需要登录后才可以回复