日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

规则引擎在数据治理平台的实践

發(fā)布時間:2023/12/15 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 规则引擎在数据治理平台的实践 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、背景

在數(shù)據(jù)治理時,經(jīng)常會遇到個性化統(tǒng)計分析的場景:基于數(shù)據(jù)的某些屬性進(jìn)行組合篩選,只有符合條件的數(shù)據(jù)才進(jìn)行統(tǒng)計分析。

傳統(tǒng)的實現(xiàn)方式是:業(yè)務(wù)人員提供篩選條件,數(shù)據(jù)開發(fā)人員在ETL任務(wù)直接開發(fā)。這種方式主要有兩個痛點:

  • 需求上線周期長
    開發(fā)人員須對ETL任務(wù)進(jìn)行開發(fā)調(diào)試、發(fā)布上線,按天、周、月排期都有可能。
  • 統(tǒng)計口徑不直觀
    篩選條件都在ETL任務(wù)中,業(yè)務(wù)人員無法直觀判斷數(shù)據(jù)是否符合預(yù)期,往往在數(shù)據(jù)量波動比較明顯的時候才會發(fā)現(xiàn)異常。

為了解決這些問題,數(shù)據(jù)治理平臺提供了給數(shù)據(jù)打標(biāo)簽的功能:業(yè)務(wù)人員在數(shù)據(jù)治理平臺上快速批量對數(shù)據(jù)打上個性化標(biāo)簽,數(shù)據(jù)開發(fā)人員只須篩選打上特定標(biāo)簽的數(shù)據(jù),而無須直接對數(shù)據(jù)進(jìn)行過濾篩選。通過這種方式,可以解決需求上線周期長、統(tǒng)計口徑不直觀的問題。

  • 數(shù)據(jù)開發(fā)人員只須一次性開發(fā)ETL任務(wù),基于標(biāo)簽進(jìn)行數(shù)據(jù)篩選即可,具體的數(shù)據(jù)篩選交由業(yè)務(wù)人員在數(shù)據(jù)治理平臺上操作。
  • 業(yè)務(wù)人員在數(shù)據(jù)治理平臺上面可以直觀查看須統(tǒng)計的數(shù)據(jù),可視化管理數(shù)據(jù)統(tǒng)計口徑。

隨著數(shù)據(jù)量的不斷增長,單靠業(yè)務(wù)人員人工管理標(biāo)簽的工作會變得越來越繁瑣:給10條數(shù)據(jù)打標(biāo)簽業(yè)務(wù)人員還可以接受,但要給成千上萬條數(shù)據(jù)打標(biāo)簽時,正常人都會抗拒這種操作了。

所以基于規(guī)則自動給數(shù)據(jù)打標(biāo)簽的需求,自然就會提上議程。當(dāng)業(yè)務(wù)人員需要的篩選條件簡單時,數(shù)據(jù)治理平臺可以快速開發(fā)功能進(jìn)行支持,但隨著業(yè)務(wù)的發(fā)展,篩選條件會變得越來越復(fù)雜。
為了支持這些條件,平臺功能會變得越來越臃腫,而且還需要投入開發(fā)人力排期開發(fā),無法快速滿足日新月異的業(yè)務(wù)需求。

因此,經(jīng)過調(diào)研之后,決定引入規(guī)則引擎Aviator,平臺基于規(guī)則引擎提供可視化配置功能,由業(yè)務(wù)人員進(jìn)行自定義配置,平臺根據(jù)業(yè)務(wù)配置自動匹配符合條件的數(shù)據(jù),打上對應(yīng)的標(biāo)簽。

本文不涉及規(guī)則引擎的調(diào)研過程,相關(guān)規(guī)則引擎的優(yōu)劣對比不在本文討論范圍。本文主要介紹規(guī)則引擎Aviator的基礎(chǔ)語法,以及在數(shù)據(jù)治理中的使用實踐。

二、規(guī)則引擎Aviator

2.1 簡介

Aviator是一個高性能、輕量級的java語言實現(xiàn)的表達(dá)式求值引擎,主要用于各種表達(dá)式的動態(tài)求值。

官方地址:https://github.com/killme2008/aviatorscript

用戶手冊:https://www.yuque.com/boyan-avfmj/aviatorscript/cpow90

2.2 關(guān)鍵函數(shù)介紹

這里主要介紹關(guān)鍵函數(shù):

字符串函數(shù)

函數(shù)名稱說明
string.contains(s1,s2)判斷 s1 是否包含 s2,返回 Boolean

Sequence 函數(shù)(集合處理)

函數(shù)名稱說明
seq.set(p1, p2, p3, …)創(chuàng)建一個 java.util.HashSet 實例,添加參數(shù)到這個集合并返回。
seq.contains_key(map, key)當(dāng) map 中存在 key 的時候(可能為 null),返回 true。對于數(shù)組和鏈表,key 可以是 index,當(dāng) index 在有效范圍[0…len-1],返回 true,否則返回 false
include(seq,element)判斷 element 是否在集合 seq 中,返回 boolean 值,對于 java.uitl.Set 是 O(1) 時間復(fù)雜度,其他為 O(n)
seq.every(seq, fun)fun 接收集合的每個元素作為唯一參數(shù),返回 true 或 false。當(dāng)集合里的每個元素調(diào)用 fun 后都返回 true 的時候,整個調(diào)用結(jié)果為 true,否則為 false。
seq.not_any(seq, fun)fun 接收集合的每個元素作為唯一參數(shù),返回 true 或 false。當(dāng)集合里的每個元素調(diào)用 fun 后都返回 false 的時候,整個調(diào)用結(jié)果為 true,否則為 false。
seq.some(seq, fun)fun 接收集合的每個元素作為唯一參數(shù),返回 true 或 false。當(dāng)集合里的只要有一個元素調(diào)用 fun 后返回 true 的時候,整個調(diào)用結(jié)果立即為該元素,否則為 nil。

示例:

// 數(shù)據(jù)字段名與字段值的映射,字段值有可能為多個,所以統(tǒng)一為數(shù)組形式,方便處理 Map<String, List<String>> propNameValueMap = new HashMap<>(1); tag.put("tagName", Arrays.asList("選項1", "選項4")); // Aviator輸入?yún)?shù) Map<String, Object> env = new HashMap<>(1); env.put("tag", propNameValueMap);// Aviator表達(dá)式,判斷Aviator輸入?yún)?shù)中是否有指定屬性 String checkPropExpression = "seq.contains_key( tag, 'tagName')";// Aviator表達(dá)式,生成符合預(yù)期的選項值集合 String expectedValueExpression = "seq.set('選項1','選項2','選項3')";// Aviator表達(dá)式,生成一個匿名函數(shù),判斷字段取值X是否在選項值集合中 String includeFunc = "lambda(x) -> include( seq.set('選項1','選項2','選項3'), x )";// 數(shù)據(jù)字段值任意一個符合篩選條件即可:通過 seq.some 函數(shù)遍歷字段取值,只要任意一個字段取值在選項值集合中即返回true // 結(jié)果:true System.out.println(AviatorEvaluator.execute("( seq.contains_key( tag, 'tagName') && seq.some( tag.tagNameCn, lambda(x) -> include( seq.set('選項1','選項2','選項3'), x ) end ) != nil )", env));// 數(shù)據(jù)字段值全部符合篩選條件:通過 seq.every 函數(shù),遍歷字段取值,當(dāng)且僅當(dāng)所有字段取值都在選項值集合中才會返回true // 結(jié)果:false System.out.println(AviatorEvaluator.execute("( seq.contains_key( tag, 'tagName') && seq.every( tag.tagName, lambda(x) -> include( seq.set('選項1','選項2','選項3'), x ) end ) )", env));// 數(shù)據(jù)字段值完全不符合篩選條件:通過 seq.not_any 函數(shù),遍歷字段取值,當(dāng)且僅當(dāng)所有字段取值都不在選項值集合中才會返回true // 結(jié)果:false System.out.println(AviatorEvaluator.execute("( seq.contains_key( tag, 'tagName') && seq.not_any( tag.tagName, lambda(x) -> include( seq.set('選項1','選項2','選項3'), x ) end ) )", env));// Aviator表達(dá)式,生成一個匿名函數(shù),判斷數(shù)據(jù)字段值是否包含特定的選項值。注意:若選項值有多個,則字段值當(dāng)中必須包含所有的選項值。 // 比如特定的選項值為兩個:“人杰”、“鬼雄”,則字符串“生當(dāng)作人杰,死亦為鬼雄”是符合要求的;若選項值變成三個“人杰”,“鬼雄”,“英雄”時,則字符串“生當(dāng)作人杰,死亦為鬼雄”不再符合要求,因為少了“英雄” String containFunc = "lambda(x) -> seq.every( seq.set('選項1'), lambda(v) -> string.contains(x, v) end )";// 數(shù)據(jù)字段值全部包含特定選項值 // 結(jié)果:false。因為字段的第二個取值“選項2”不包含字符串“選項1” System.out.println(AviatorEvaluator.execute("( seq.contains_key( tag, 'tagName') && seq.every( tag.tagName, lambda(x) -> seq.every( seq.set('選項1'), lambda(v) -> string.contains(x, v) end ) end ) )", env));

三、規(guī)則定義

3.1 數(shù)據(jù)匹配

目前業(yè)務(wù)側(cè)暫只需要對數(shù)據(jù)進(jìn)行匹配,不涉及數(shù)據(jù)計算。
因此基于常見的用戶場景,數(shù)據(jù)治理平臺抽象出兩種運算符:比較運算符、范圍運算符。

  • 比較運算符

定義如何比較字段取值與預(yù)期值。平臺目前提供了三種比較方式:等于,不等于,包含。

  • 范圍運算符

由于字段取值與預(yù)期值都可能是多個,統(tǒng)一以數(shù)組形式存儲數(shù)據(jù),通過比較運算符得到每個字段值與預(yù)期值的比較結(jié)果后,須通過范圍運算符定義多個比較結(jié)果如何進(jìn)行組合運算,得到最終結(jié)果。平臺目前提供了三個運算符:任意符合,全部符合,完全不符合。

示例:

字段取值比較運算符范圍運算符預(yù)期值匹配結(jié)果說明
[選項1, 選項4]等于任意符合[選項1, 選項2, 選項3]true只要字段取值任意一個在預(yù)期值當(dāng)中,即為true。選項1在預(yù)期值中,所以為true。
[選項1, 選項4]等于全部符合[選項1, 選項2, 選項3]false當(dāng)且僅當(dāng)字段取值全部在預(yù)期值當(dāng)中,才為true。選項4不在預(yù)期值中,所以為false。
[選項1, 選項4]等于完全不符合[選項1, 選項2, 選項3]false當(dāng)且僅當(dāng)字段取值全部不在預(yù)期值當(dāng)中,才為true。選項1在預(yù)期值中,所以為false。
[選項1, 選項4]不等于任意符合[選項1, 選項2, 選項3]true只要字段取值任意一個不在預(yù)期值當(dāng)中,即為true。選項4不在預(yù)期值中,所以為true。
[選項1, 選項4]不等于全部符合[選項1, 選項2, 選項3]false當(dāng)且僅當(dāng)字段取值全部不在預(yù)期值當(dāng)中,才為true。選項1在預(yù)期值中,所以為false。
[選項1, 選項4]不等于完全不符合[選項1, 選項2, 選項3]false當(dāng)且僅當(dāng)字段取值全部都在預(yù)期值當(dāng)中,才為true。選項4不在預(yù)期值中,所以為false。
["生當(dāng)作人杰,死亦為鬼雄", "英雄難過美人關(guān)"]包含任意符合[人杰, 鬼雄]true只要字段取值任意一個包含所有的預(yù)期值,即為true。第一個字段取值包含了所有預(yù)期值,所以為true。
["生當(dāng)作人杰,死亦為鬼雄", "英雄難過美人關(guān)"]包含全部符合[人杰, 鬼雄]false當(dāng)且僅當(dāng)所有的字段取值都包含所有的預(yù)期值,即為true。第二個字段取值不包含預(yù)期值,所以為false。
["生當(dāng)作人杰,死亦為鬼雄", "英雄難過美人關(guān)"]包含完全不符合[人杰, 鬼雄]false當(dāng)且僅當(dāng)所有字段取值都不包含所有的預(yù)期值,即為true。第一個字段取值包含了所有預(yù)期值,所以為false。

3.2 業(yè)務(wù)邏輯

數(shù)據(jù)匹配只能針對單個字段,業(yè)務(wù)往往需要針對多個字段進(jìn)行組合排列,根據(jù)多個字段的匹配結(jié)果進(jìn)行取舍。
因此數(shù)據(jù)治理平臺提供了邏輯運算符,對多個字段的匹配結(jié)果進(jìn)行與或運算。

  • 邏輯運算符

定義如何將多個字段的匹配結(jié)果進(jìn)行與或運算,得到最終匹配結(jié)果。平臺提供了兩個運算符:與,或。

3.3 規(guī)則參數(shù)

基于數(shù)據(jù)匹配與業(yè)務(wù)邏輯,數(shù)據(jù)治理平臺抽象出以下數(shù)據(jù)結(jié)構(gòu),方便業(yè)務(wù)進(jìn)行個性化配置:

/*** 標(biāo)簽規(guī)則條件,指定各表達(dá)式之間的邏輯關(guān)系** @author chriscchen* @createtime 2022-07-30*/ @NoArgsConstructor @AllArgsConstructor @Data @Builder @JsonInclude(Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown = true) public class TagRuleCondition {/*** 邏輯運算符,定義如何將規(guī)則條件與規(guī)則表達(dá)式進(jìn)行與或運算 {@link LogicOperator}*/private String logic;/*** 嵌套的規(guī)則條件。當(dāng)需要對多個字段進(jìn)行組合排列時,須嵌套規(guī)則條件。*/private List<TagRuleCondition> conditions;/*** 規(guī)則表達(dá)式,可直接對字段進(jìn)行數(shù)據(jù)匹配*/private List<TagRuleExpression> expressions; }/*** 標(biāo)簽規(guī)則表達(dá)式** @author chriscchen* @createtime 2022-07-30*/ @NoArgsConstructor @AllArgsConstructor @Data @Builder @JsonInclude(Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown = true) public class TagRuleExpression {/*** 字段名*/private String name;/*** 比較運算符 {@link CompareOperator}*/private String comparator;/*** 范圍運算符 {@link ScaleOperator}*/private String scale;/*** 預(yù)期值*/private List<Object> value; }

示例:
假設(shè)有2條數(shù)據(jù)如下:

名稱狀態(tài)分類廠商
飛天銷售中醬香型茅臺
五糧液銷售中濃香型五糧液

需要篩選狀態(tài)為銷售中,并且分類為醬香型的數(shù)據(jù),生成的數(shù)據(jù)結(jié)構(gòu)如下:

{"logic": "AND","expressions": [{"name": "狀態(tài)","comparator": "=","scale": "any","value": ["銷售中"]},{"name": "分類","comparator": "=","scale": "any","value": ["醬香型"]}] }

3.4 表達(dá)式轉(zhuǎn)換

基于3.3節(jié)的數(shù)據(jù)結(jié)構(gòu),參考2.2節(jié)的示例,生成Aviator表達(dá)式

/*** 根據(jù)用戶配置的規(guī)則條件,生成Aviator的表達(dá)式** @param condition 用戶配置的規(guī)則條件* @param keyPrefix 有嵌套屬性時,需要加上屬性前綴* @return Aviator的表達(dá)式*/private static String convertToAviatorExpression(TagRuleCondition condition, String keyPrefix)throws AbstractDataMapException {if (condition == null) {throw new CommonParamUnacceptableException("標(biāo)簽的規(guī)則條件不能為空");}if (StringUtils.isBlank(condition.getLogic())) {throw new CommonParamMissedException("缺少邏輯運算符,請檢查參數(shù):logic");}List<String> aviatorExpressions = new ArrayList<>();// 嵌套的規(guī)則條件。當(dāng)需要對多個字段進(jìn)行組合排列時,須嵌套規(guī)則條件if (CollectionUtils.isNotEmpty(condition.getConditions())) {for (TagRuleCondition subCondition : condition.getConditions()) {aviatorExpressions.add(convertToAviatorExpression(subCondition, keyPrefix));}}// 規(guī)則表達(dá)式,可直接對字段進(jìn)行數(shù)據(jù)匹配if (CollectionUtils.isNotEmpty(condition.getExpressions())) {for (TagRuleExpression expression : condition.getExpressions()) {String valueSet = generateValueSetExpression(expression);// 檢查屬性是否存在String check = "seq.contains_key( " + keyPrefix + expression.getType()+ ", '" + expression.getName() + "')";// 屬性字段名String propValue = keyPrefix + expression.getType() + "." + expression.getName();generateTagExpression(aviatorExpressions, expression, valueSet, check, propValue);}}switch (condition.getLogic()) {case LogicOperator.AND:return StringUtils.join(aviatorExpressions, " && ");case LogicOperator.OR:return StringUtils.join(aviatorExpressions, " || ");default:throw new CommonParamUnacceptableException("未知邏輯運算符,請檢查參數(shù):" + condition.getLogic());}}/*** 基于用戶配置的規(guī)則表達(dá)式,生成預(yù)期值表達(dá)式** @param expression 用戶配置的規(guī)則表達(dá)式* @return 預(yù)期值表達(dá)式*/private static String generateValueSetExpression(TagRuleExpression expression) {List<Object> value = expression.getValue();String valueSet;if (CollectionUtils.isEmpty(value)) {valueSet = "seq.set()";} else {Object elem = value.get(0);if (elem instanceof String) {// 字符串加上引號valueSet = "seq.set('" + StringUtils.join(value, "','") + "')";} else {// 其余類型直接拼接valueSet = "seq.set(" + StringUtils.join(value, ",") + ")";}}return valueSet;}/*** 生成標(biāo)簽類型的Aviator表達(dá)式** @param aviatorExpressions 生成的Aviator表達(dá)式,添加到此數(shù)組中* @param expression 用戶配置的規(guī)則表達(dá)式數(shù)據(jù)結(jié)構(gòu)* @param valueSet 提前生成的預(yù)期值集合表達(dá)式* @param check 提前生成的檢測屬性存在的表達(dá)式* @param propValue 屬性字段名* @throws AbstractDataMapException exception*/private static void generateTagExpression(List<String> aviatorExpressions,TagRuleExpression expression, String valueSet, String check, String propValue)throws AbstractDataMapException {if (StringUtils.isBlank(expression.getComparator())) {throw new CommonParamMissedException("缺少比較運算符,請檢查參數(shù):operation");}if (StringUtils.isBlank(expression.getScale())) {throw new CommonParamMissedException("缺少范圍運算符,請檢查參數(shù):scale");}switch (expression.getComparator()) {case CompareOperator.E: {generateTagEqualExpression(aviatorExpressions, expression, valueSet, check, propValue);break;}case CompareOperator.NE: {generateTagNotEqualExpression(aviatorExpressions, expression, valueSet, check, propValue);break;}case CompareOperator.CONTAIN: {generateTagContainExpression(aviatorExpressions, expression, valueSet, check, propValue);break;}default: {throw new CommonParamUnacceptableException("未知比較運算符,請檢查參數(shù):" + expression.getComparator());}}}/*** 生成標(biāo)簽類型 “等于” 的Aviator表達(dá)式** @param aviatorExpressions 生成的Aviator表達(dá)式,添加到此數(shù)組中* @param expression 用戶配置的規(guī)則表達(dá)式數(shù)據(jù)結(jié)構(gòu)* @param valueSet 提前生成的預(yù)期值集合表達(dá)式* @param check 提前生成的檢測屬性存在的表達(dá)式* @param propValue 屬性字段名* @throws AbstractDataMapException exception*/private static void generateTagEqualExpression(List<String> aviatorExpressions,TagRuleExpression expression, String valueSet, String check, String propValue)throws AbstractDataMapException {switch (expression.getScale()) {case ScaleOperator.ANY: {aviatorExpressions.add("( " + check + " && seq.some( " + propValue+ ", lambda(x) -> include( " + valueSet + ", x ) end ) != nil )");break;}case ScaleOperator.ALL: {aviatorExpressions.add("( " + check + " && seq.every( " + propValue+ ", lambda(x) -> include( " + valueSet + ", x ) end ) )");break;}case ScaleOperator.NONE: {aviatorExpressions.add("( " + check + " && seq.not_any( " + propValue+ ", lambda(x) -> include( " + valueSet + ", x ) end ) )");break;}default:throw new CommonParamUnacceptableException("未知范圍運算符,請檢查參數(shù):" + expression.getScale());}}/*** 生成標(biāo)簽類型 “不等于” 的Aviator表達(dá)式** @param aviatorExpressions 生成的Aviator表達(dá)式,添加到此數(shù)組中* @param expression 用戶配置的規(guī)則表達(dá)式數(shù)據(jù)結(jié)構(gòu)* @param valueSet 提前生成的預(yù)期值集合表達(dá)式* @param check 提前生成的檢測屬性存在的表達(dá)式* @param propValue 屬性字段名* @throws AbstractDataMapException exception*/private static void generateTagNotEqualExpression(List<String> aviatorExpressions,TagRuleExpression expression, String valueSet, String check, String propValue)throws AbstractDataMapException {switch (expression.getScale()) {case ScaleOperator.ANY: {aviatorExpressions.add("( " + check + " && seq.some( " + propValue+ ", lambda(x) -> include( " + valueSet + ", x ) == false end ) != nil )");break;}case ScaleOperator.ALL: {aviatorExpressions.add("( " + check + " && seq.not_any( " + propValue+ ", lambda(x) -> include( " + valueSet + ", x ) end ) )");break;}case ScaleOperator.NONE: {aviatorExpressions.add("( " + check + " && seq.every( " + propValue+ ", lambda(x) -> include( " + valueSet + ", x ) end ) )");break;}default:throw new CommonParamUnacceptableException("未知范圍運算符,請檢查參數(shù):" + expression.getScale());}}/*** 生成標(biāo)簽類型 “包含” 的Aviator表達(dá)式** @param aviatorExpressions 生成的Aviator表達(dá)式,添加到此數(shù)組中* @param expression 用戶配置的規(guī)則表達(dá)式數(shù)據(jù)結(jié)構(gòu)* @param valueSet 提前生成的預(yù)期值集合表達(dá)式* @param check 提前生成的檢測屬性存在的表達(dá)式* @param propValue 屬性字段名* @throws AbstractDataMapException exception*/private static void generateTagContainExpression(List<String> aviatorExpressions,TagRuleExpression expression, String valueSet, String check, String propValue)throws AbstractDataMapException {switch (expression.getScale()) {case ScaleOperator.ANY: {aviatorExpressions.add("( " + check + " && seq.some( " + propValue+ ", lambda(x) -> seq.every( " + valueSet+ ", lambda(v) -> string.contains(x, v) end ) end ) != nil )");break;}case ScaleOperator.ALL: {aviatorExpressions.add("( " + check + " && seq.every( " + propValue+ ", lambda(x) -> seq.every( " + valueSet+ ", lambda(v) -> string.contains(x, v) end ) end ) )");break;}case ScaleOperator.NONE: {aviatorExpressions.add("( " + check + " && seq.not_any( " + propValue+ ", lambda(x) -> seq.every( " + valueSet+ ", lambda(v) -> string.contains(x, v) end ) end ) )");break;}default:throw new CommonParamUnacceptableException("未知范圍運算符,請檢查參數(shù):" + expression.getScale());}}

3.5 數(shù)據(jù)轉(zhuǎn)換

規(guī)則引擎Aviator需要將數(shù)據(jù)轉(zhuǎn)換為Map<String, Object>類型,作為輸入?yún)?shù)。

// 生成原始數(shù)據(jù) Map<String, Object> rawData = new ObjectMapper().convertValue(record, new TypeReference<Map<String, Object>>() {});// 字段名與字段取值的映射 { propName -> [ propValue ] },字段取值統(tǒng)一以數(shù)組形式 Map<String, Object> nameValueMap = new HashMap<>(rawData.size())); rawData.forEach((key, value) -> tagNameValueMap.put(key, Collections.singletonList(value)));

3.6 規(guī)則匹配

// 預(yù)編譯表達(dá)式,提高效率Expression aviatorExpression;try {aviatorExpression = AviatorEvaluator.compile("...");} catch (Exception e) {throw new CommonParamUnacceptableException("規(guī)則異常,請檢查:" + e.getMessage(), e);}// 匹配數(shù)據(jù)Boolean result = (Boolean) aviatorExpression.execute(nameValueMap);

四、總結(jié)

基于規(guī)則引擎Aviator開發(fā)的自定義規(guī)則功能,既能讓業(yè)務(wù)直接進(jìn)行個性化規(guī)則配置,快速對匹配的數(shù)據(jù)打標(biāo)簽,也極大解放了平臺開發(fā)的人力,從重復(fù)乏味的定制化功能開發(fā)抽身出來,為業(yè)務(wù)實現(xiàn)更有價值的功能。

本文只介紹自定義規(guī)則功能中的核心處理模塊,還須基于數(shù)據(jù)結(jié)構(gòu)進(jìn)行前端開發(fā),支持可視化配置,不再一一展開。

總結(jié)

以上是生活随笔為你收集整理的规则引擎在数据治理平台的实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。