Easy-Rules 规则引擎,不能同时触发多个事实
Easy-Rules Rule engine, cannot fire on multiple facts at once
我正在尝试将简单规则的商店教程 (shop) 扩展到多个 facts
上的 运行。在规则中编写条件时,我们使用 "fact name" 调用函数,如下所示,
condition: "people.isAdult() == false"
因为people
只是facts
中一个对象实例的名字,像上面那样定义条件是不行的。我如何定义条件以使其遍历多个 facts
.
我想要实现的是在规则引擎的一次火灾中评估多个事实的规则。
当将一组具有相同事实名称的事实提供给规则引擎时,仅评估最后提供的一个。但是,当为每个事实分配不同的名称时,我无法为每个事实分配相同的条件。
下面是代码。假设 Person
class 对所有成员都有基本的 get/set 功能。
Rules.yml:
---
name: "regex"
description: "Check if regex pattern matches"
priority: 1
condition: "people.getPayload().matches(\".*12.*34$\") == true"
actions:
- "System.out.println(\"There is a match\");"
---
name: "age"
description: "Check if person's age is > 18 and marks the person as adult"
priority: 2
condition: "people.age > 18"
actions:
- "people.setAdult(true);"
---
name: "alkol"
description: "children are not allowed to buy alcohol"
priority: 3
condition: "people.isAdult() == false"
actions:
- "System.out.println(\"Shop: Sorry, you are not allowed to buy portakal\");"
主线:
//create a person instance (fact)
Person [] PeopleArray = new Person [100];
Person [] KidsArray = new Person [300];
// initialize arrays
for(int i = 0; i < PeopleArray.length ; i++)
{
PeopleArray[i] = new Person("TOM"+i,23);
PeopleArray[i].setPayload(dummystring);
}
for(int i = 0; i < KidsArray.length ; i++)
{
KidsArray[i] = new Person("EMRE"+i,13);
KidsArray[i].setPayload(dummystring);
}
Facts facts = new Facts();
// create a rule set
Rules rules = MVELRuleFactory.createRulesFrom(new FileReader("rules.yml"));
RulesEngine rulesEngine = new DefaultRulesEngine();
System.out.println("Tom: Hi! can I have some Vodka please?");
//put the facts
for(int i = 0; i < PeopleArray.length ; i++)
facts.put("people", PeopleArray[i]);
long start = System.currentTimeMillis();
for(int i = 0; i < KidsArray.length ; i++)
facts.put("people", KidsArray[i]);
rulesEngine.fire(rules, facts);
一个Facts
对象本质上是一个hashmap。所以按照设计,你不能把两个事实放在同一个键上。
我在您的示例中看到 people
事实是一个数组。现在如何在 mvel 表达式中处理数组是另一回事了。老实说,我能给出的最佳答案是查看 MVEL 文档:https://github.com/imona/tutorial/wiki/MVEL-Guide#arrays
What I want to achieve is evaluate the rules on multiple facts in one fire of the rule engine.
我不确定这是否可以通过简单的规则实现。我认为你可以:
- 要么平面图你的事实
- 或者根据不同的事实多次调用
fire
希望这对您有所帮助。
Fact
其实就是一个Map
Map<String, Object> facts = new HashMap<>() // from source code
如果您需要添加多个事实,然后使用它们同时触发规则,您可以使用 List
来完成。可以创建一个 List<Object>
并将此 List
添加到 Facts
.
规则Class:
@Rule(name = "Hello World rule", description = "Always say hello world")
public class HelloWorldRule {
@Condition
public boolean when() {
return true;
}
@Action
public void then(@Fact("facts") List<Object> arr) throws Exception {
for (Object i : arr) {
System.out.print(i + ", ");
}
}
}
启动器Class:
public class Launcher {
public static void main(String[] args) {
// create facts
Facts facts = new Facts();
List<Object> arr = new ArrayList<>();
arr.add("hello");
arr.add(5);
facts.put("facts", arr);
// create rules
Rules rules = new Rules();
rules.register(new HelloWorldRule());
// create a rules engine and fire rules on known facts
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
请记住,如果您拥有相同类型的所有对象而不是 Object
,这将非常有用,就像在本例中 Person
.
我正在尝试将简单规则的商店教程 (shop) 扩展到多个 facts
上的 运行。在规则中编写条件时,我们使用 "fact name" 调用函数,如下所示,
condition: "people.isAdult() == false"
因为people
只是facts
中一个对象实例的名字,像上面那样定义条件是不行的。我如何定义条件以使其遍历多个 facts
.
我想要实现的是在规则引擎的一次火灾中评估多个事实的规则。
当将一组具有相同事实名称的事实提供给规则引擎时,仅评估最后提供的一个。但是,当为每个事实分配不同的名称时,我无法为每个事实分配相同的条件。
下面是代码。假设 Person
class 对所有成员都有基本的 get/set 功能。
Rules.yml:
---
name: "regex"
description: "Check if regex pattern matches"
priority: 1
condition: "people.getPayload().matches(\".*12.*34$\") == true"
actions:
- "System.out.println(\"There is a match\");"
---
name: "age"
description: "Check if person's age is > 18 and marks the person as adult"
priority: 2
condition: "people.age > 18"
actions:
- "people.setAdult(true);"
---
name: "alkol"
description: "children are not allowed to buy alcohol"
priority: 3
condition: "people.isAdult() == false"
actions:
- "System.out.println(\"Shop: Sorry, you are not allowed to buy portakal\");"
主线:
//create a person instance (fact)
Person [] PeopleArray = new Person [100];
Person [] KidsArray = new Person [300];
// initialize arrays
for(int i = 0; i < PeopleArray.length ; i++)
{
PeopleArray[i] = new Person("TOM"+i,23);
PeopleArray[i].setPayload(dummystring);
}
for(int i = 0; i < KidsArray.length ; i++)
{
KidsArray[i] = new Person("EMRE"+i,13);
KidsArray[i].setPayload(dummystring);
}
Facts facts = new Facts();
// create a rule set
Rules rules = MVELRuleFactory.createRulesFrom(new FileReader("rules.yml"));
RulesEngine rulesEngine = new DefaultRulesEngine();
System.out.println("Tom: Hi! can I have some Vodka please?");
//put the facts
for(int i = 0; i < PeopleArray.length ; i++)
facts.put("people", PeopleArray[i]);
long start = System.currentTimeMillis();
for(int i = 0; i < KidsArray.length ; i++)
facts.put("people", KidsArray[i]);
rulesEngine.fire(rules, facts);
一个Facts
对象本质上是一个hashmap。所以按照设计,你不能把两个事实放在同一个键上。
我在您的示例中看到 people
事实是一个数组。现在如何在 mvel 表达式中处理数组是另一回事了。老实说,我能给出的最佳答案是查看 MVEL 文档:https://github.com/imona/tutorial/wiki/MVEL-Guide#arrays
What I want to achieve is evaluate the rules on multiple facts in one fire of the rule engine.
我不确定这是否可以通过简单的规则实现。我认为你可以:
- 要么平面图你的事实
- 或者根据不同的事实多次调用
fire
希望这对您有所帮助。
Fact
其实就是一个Map
Map<String, Object> facts = new HashMap<>() // from source code
如果您需要添加多个事实,然后使用它们同时触发规则,您可以使用 List
来完成。可以创建一个 List<Object>
并将此 List
添加到 Facts
.
规则Class:
@Rule(name = "Hello World rule", description = "Always say hello world")
public class HelloWorldRule {
@Condition
public boolean when() {
return true;
}
@Action
public void then(@Fact("facts") List<Object> arr) throws Exception {
for (Object i : arr) {
System.out.print(i + ", ");
}
}
}
启动器Class:
public class Launcher {
public static void main(String[] args) {
// create facts
Facts facts = new Facts();
List<Object> arr = new ArrayList<>();
arr.add("hello");
arr.add(5);
facts.put("facts", arr);
// create rules
Rules rules = new Rules();
rules.register(new HelloWorldRule());
// create a rules engine and fire rules on known facts
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
请记住,如果您拥有相同类型的所有对象而不是 Object
,这将非常有用,就像在本例中 Person
.