drools-对象筛选扩展

本文深入探讨了DRL查询语言的各种高级用法,包括类型判断、属性连接、对象筛选、属性多条件递归等核心功能,并介绍了日期字符化、集合操作、子类型判断等实用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类型判断

                // int age
		
		// 查询时条件不分类型,一般直接匹配到自动识别
		Person(name=="godme",age==88)
		// 类型不对会尝试强制转换,转换成功后继续操作
		Person(name=="godme",age=="88")
		// 类型强转失败,直接报错
		Person(name=="godme",age=="aa")
		// 该机制可以规避一些小错误,但是尽量规范,毕竟错误隐蔽

属性连接

		// 以下筛选,单独不并列,为了明显显示,没做注释
		
		// 一般逗号分隔,默认 && 连接
		Person(name == "godme", male == "male", age < 100)
		// 显式声明
		Person(name == "godme" && male == "male" && age < 100)
		// 自由组合
		Person(name == "godme" && male == "male" || age < 100)
		Person(name == "godme" || male == "male" && age < 100)
		// 分组
		Person((name == "godme" && male == "female" || age < 100))
		Person(name == "godme" && (male == "male" || age < 100))
		// 小问题:
		Person(name == "godme",male == "male"|| age < 100)		// 成功
		Person(name == "godme"||male == "male", age < 100)  	// 成功
		Person(name == "godme"&&male == "male"|| age < 100)		// 成功
		Person((name == "godme" &&male == "male")|| age < 100)	// 成功
		Person((name == "godme",male == "male")|| age < 100) 	// 失败,drl直接提示错误
		// 括号分组,内部必须显式声明连接符,不采用括号时,可以局部用连接符直接关联,复用逗号and
		
		// 优先级
		//	1. &&
		//	2. |
		//	3. ,
		

对象筛选和属性提取

		// 属性有两部分功用
		// 1. 对象筛选
		// 2. 值绑定
		
		// 一般情况:先筛选,再绑定
		Person(age > 20, $age:age)
		// 筛选时主要看真值,属性可以直接进行复杂运算来计算真值
		Person(age * 3 < 180 , $age:age)
		// 合一使用,直接绑定,后续真值,名称部分自动绑定对应的属性值,而不是真值结果
		Person($age:age<100)
		
		// 另一种类型,非空判断
		Person(name != null , $name:name)
		// 二合一
		Person($name:name!=null)
		// 更常用的是属性对象再取值
		Person(name="godme", address != null, $city:address.getCity())
		// 二合一
		Person(name=="godme", $city:address!.getCity())	

属性多条件递归

		// 一般属性多条件采用枚举方式进行限制
		Person(age < 100, age > 0)
		// 递归方式
		Person(age(<100&&>0)) //Person(age(<100,>0)) 失败,属性递归中必须显式声明连接符
		
		// 复杂一点
		// 1. 年龄规范   0<age<100
		// 2. 年龄分组	young:10<age<30  old: 60<age<80
		Person(age>0 , age < 100 , age >10 && age < 30 || (age <80 && age > 60))
		// 简化一点
		Person((age>0 && age < 100) && ((age >10 && age < 30) || (age <80 && age > 60)))
		// 直接大招
		Person(age(>0&&<100)&&((>10&&<30)||(>60&&<80)))
		// 熟悉以后,直接写出来就行了
		// 有点生疏的话,先规范的分好组,然后"提公因式"就好了

属性分组查询

		// 和多条件异曲同工,都是可以"提公因式"
		Person(age(>0&&<100)&&((>10&&<30)||(>60&&<80)))
		// 属性对象多重筛选
		Person(address.city == "China", address.country == "Earth")
		// 聚合
		Person(address.(city == "China", country== "Earth"))
		// 和属性多条件过滤差不多,需要注意的就是属性调用的".", 还可以加上非空
		Person(address != null, address.city == "China", address.country == "Earth")
		Person(address!.(city == "China", country== "Earth"))

日期字符化

		// 一般判断时间都是通过毫秒值进行判断
		// 即使是其他判断方式也是基于此
		// 只是用起来的确不够方便,也不够直观
		Person(birth.getTime() > new Date().getTime())
		
		
		// 时间字符化
		// 通过设置drools本身默认的时间格式 drools.dateformat,就可以直接用格式化字符串表示时间了
		//		System.setProperty("drools.dateformat", "yyyy-MM-dd")
		
		Person(bitrh == "2018-Dec-23")

集合

		// 对于drl中集合类型的操作,java中的操作的确可以沿用
		// 1. 方法调用
		list(index).getAge() == 18
		map.get(name).isValid()
		// 这种办法,基本都是对"对象"的接口("方法")调用
		
		// 2. 属性调用
		// drl中也可以直接进行属性调用 
		list[index].age == 18
		map[name].valid
		// 都是[]数组形式的直接调用
		
		
		// 说起来,对象之中也能够发现这种现象
		// 属性
		Person(name == "godme")
		// 方法
		Person(getName() == "godme")

子类型判断

		// 对于复合类型而言,需要区别对待
		// 这种复合一般针对继承而言
		// 用一个顶层父类进行接收,最终需要追溯到最底层,就要进行类型的判断了
		Person(address != null, address instanceof Location , $city:address.city)
		// instance 就是追溯类别,进行类型判断
		
		// 有时候还需要进行强转操作
		// 对象也可以进行全路径的指定,带全名称空间(包名)而已,就不多讨论了
		Person(address != null, address instanceof Location , $city:address#Location.city)
		// 层级强转 + 关注对象变换 +  判断
		Person(address != null, address#Location.city#DetailCity.population > 1000)
		// +非空
		Person(address != null, address#Location!.city#DetailCity!.population > 1000)
		Person(address!#Location!.city#DetailCity!.population > 1000)  
		// 猜测, 未实践,不知道强转前能不能进行非空的融合判断

		// 疑问
		//#这不是注释么,后续的好像都注释掉了,我这个实验不太成功
		// 不过官方文档好像是这样,先就这样吧

位置参数

drl

package com.sample;

// 声明类
declare Person
	name:String
	age:int
	male:String
end


rule "attr_filter"
	when
		//平时筛选都需要指定参数名称和参数值
		Person(name == "godme", age == 45, male == "male") // 可以简便一点么
		
		// 和方法调用一个样,只要记住了属性的声明顺序,也是可以"对号入座"的
		// 声明看上方
		
		// 上一句也可以写作
		Person("godme",45,"male";)
		
		// 这个叫做位置参数,也就是对号入座
		// 严格区分筛选的条件填写部分,可以分作两部分
		//	1. 位置参数
		//	2. 条件参数
		// 中间用分号";"进行就行,前面是位置参数,后面是条件参数
		
		// 重要
		
		// 0. 分隔
		//		分号别忘记,也别用错
		// 1. 顺序
		// 		从上一句能看出来,填写的顺序是按照声明顺序来的,记不住就大发了
		
		// 2. 默认
		// 		当对号入座发现属性有值,就开始筛选,如果没有属性值的话,就会把设置的"筛选值"当做"默认值"置入对象
		
		// 3. 指定
		// 		位置参数虽然都是"对号入座",不过也是可以进行指定的
		Person(age==88) // 这个看不出来,需要综合一下
		$p:Person(age=="45";name == "godme") // 可能觉得神经病,但是这的确是没问题
		// Person(age==45;name == "godme") // 直接上数字会报错,只能幸好我会"强转"
		
		// 其他
		Person("godme";)  // 单独位置参数也必须有分号";", 默认的是条件参数
		
		
		// 全部亲测, 放心食用, 只是都是单条用,为了明显点才没注释
	then
		System.out.println($p);
end

java

    public static final void main(String[] args) {
        try {
            KnowledgeBase kbase = readKnowledgeBase();
            StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
            KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
            FactType personClasee = kbase.getFactType("com.sample", "Person");
            Object person = personClasee.newInstance();
            HashMap<String, Object> attrs = new HashMap<>();
            attrs.put("name", "godme");
            attrs.put("age", 45);
            attrs.put("male", "male");
            personClasee.setFromMap(person, attrs);
            
            ksession.insert(person);
            ksession.fireAllRules();
            logger.close();
            
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

字符串检测

		// 字符串检测
		
		// 发音检测(这特么都有)
		// 中文没试
		Person( name soundslike "foobar") // fubar 能匹配
		
		// 开头
		Person(name str[startsWith] "g")
		
		// 结尾
		Person(name str[endWith] "me")
		
		// 长度检测
		Person(name str[length] 5)

多选

		// 其中
		Person(name in ("godme", "judas"))
		// 不再其中
		Person(name not in ("godme", "judas"))

真值计算

		// 简单的真值判断执行,返回真值
		eval(2 > 3)
		// 常用
		eval(true)
		eval(false)

笛卡尔积

		// 多对象的查询,和SQL查询办法类似,会产生笛卡尔积
		$man:Person($man_age:age, male == "male")
		$woman:Person($woman_age:age, male == "female")
		eval($man_age - $woman_age == 2)
		// 结果返回的是男比女年龄大两岁的遍历组合
		
		// 查询过程中会产生笛卡尔积,然后通过其他语句控制输出
		// 笛卡尔积,简单理解就是元素的组合遍历,具体可以自行"想象"(学习)-----(西游筋?唐山葬?)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值