当前位置: 首页 > 知识库问答 >
问题:

动态在drools文件中创建新的Map

严兴言
2023-03-14

场景:
根据少数规则奖励学生。在这里,每个学生都有资格获得多项奖励,如成绩为80分的学生可以同时获得award\u 65和award\u 75。因此,在评估结果后,我想要一份学生有资格获得的奖项列表
这个用例有点不切实际,但我尝试将其与我的问题进行类比(无法发布,因为它包含敏感信息)

List<Object> getDroolsFacts(Student student, List<StudentAward> studentAwards) {
..........
}

示例规则如下:

//Assuming all the imports are perfectly done
import java.util.*;

rule "award_65"
when
  $Student: Student(status == "active" && marks > 65);
  $studentAwards: List();    // DOUBT - I
  Map<String, String> metadata = new HashMap<>();   // DOUBT - II
  metadata.put("status", "active");
  metadata.put("marks", "65");
then
  final StudentAward studentAward = StudentAward.from("Award65" , metadata);
  $studentAwards.add(studentAward);
end

rule "award_75"
when
  $Student: Student(status == "active" && marks > 75);
  $studentAwards: List();    // DOUBT - I
  Map<String, String> metadata = new HashMap<>();   // DOUBT - II
  metadata.put("status", "active");
  metadata.put("marks", "75");
then
  final StudentAward studentAward = StudentAward.from("Award75" , metadata);
  $studentAwards.add(studentAward);
end

如果一个学生有80分,那么根据当前的分数(即没有元数据相关行),我可以在结果列表中获得两个对象

DOUBT-I:(请参阅作为DOUBT-I提到的代码片段)

  • Does$studentAwards:List() 对应提供给drools的列表,还是正在创建新列表?因为目前在评估了规则之后,我能够按照其中的预期获取多个响应

DOUBT-II:(请参阅作为DOUBT-II提到的代码片段)

  • 元数据相关的3行是我新添加的,不起作用。我想实现一个场景,在这个场景中,我动态创建一个HashMap并添加一些数据,这些数据将被设置为StudentAwards对象的一部分。需要为每个规则创建新地图,并将为每个学生对象执行多个规则,结果包含所有适用的奖励
  • 那么如何创建新的地图

共有1个答案

司马狐若
2023-03-14
匿名用户

你在用一种有趣的方式来处理这件事。您的规则不起作用的部分原因是您试图将结果放入条件部分。

我们可以把你的问题分解成以下几点。

鉴于:

  • 有地位和分数的学生

规则1:

  • 状态=激活和标记时

规则2:

  • 状态=激活和标记时

这很直截了当。

到目前为止,我们的规则如下:

rule "Student is eligible for Award65"
when
  Student( status == "active", marks > 65 )
then 
  // TODO
end

rule "Student is eligible for Awards75"
when
  Student( status == "active", marks > 75)
then
  // TODO
end

到目前为止,一切顺利。

现在,我们如何真正做到“有资格获得XX奖”聚会?看看您的示例,您的规则输入包括一个列表

现在,我们可以更新上述规则中的TODO注释来实现这一点:

rule "Student is eligible for Award65"
when
  $awards: List()
  Student( status == "active", marks > 65 )
then 
  Map<String, String> metadata = new HashMap<>();
  metadata.put("status", "active");
  metadata.put("marks", "65");
  StudentAward studentAward = StudentAward.from("Award65" , metadata);
  $awards.add(studentAward);
end

rule "Student is eligible for Awards75"
when
  $awards: List()
  Student( status == "active", marks > 75)
then
  Map<String, String> metadata = new HashMap<>();
  metadata.put("status", "active");
  metadata.put("marks", "75");
  StudentAward studentAward = StudentAward.from("Award75" , metadata);
  $awards.add(studentAward);
end

就这样。剩下的就是实际调用规则。

public List<StudentAward> getAwardsForStudent(Student student) {
    KieServices kieServices = KieServices.Factory.get();
    KieContainer kContainer = kieServices.getKieClasspathContainer();
    KieBase kBase = kContainer.getKieBase(kbaseName);
    
    List<StudentAward> awards = new ArrayList<>();

    KieSession session = kBase.newKieSession();
    session.insert(student); // insert the Student 
    session.insert(awards); // insert the list of awards
    session.fireAllRules();

    return awards; // at this point, awards contains all of the values from the rules
}

就这样。给一个学生,我们执行规则,拿出一份奖励清单。

您的规则唯一真正的问题是,您将元数据映射设置在了规则的错误一侧(这是规则后果的一部分,而不是条件),以及您如何获得奖励列表。

这个答案中的规则有很多重复的代码,但是由于我们正在处理一个“玩具”示例,我不想在重构为共享函数时浪费太多精力。如果您确实使用了类似的东西,您会想看看是否可以使用共享函数甚至继承来简化您的规则。

你问了两个具体的问题。我唯一没有明确回答的是:

$studentAwards:List()是否对应于提供给drools的列表,还是正在创建的新列表?

“when”子句中不会创建任何内容。这些都是条件。此行的意思是“在工作内存中获取列表,并将其分配给变量$studentAwards

如果您的工作内存中有多个列表,这就会出现问题,这就是为什么我通常建议不要将这样的集合放入内存中。我通常的建议是创建某种“结果”对象,其中包含您期望规则输出的计算数据

请注意,在Drools的某些版本中,我在尝试使用参数化类型时遇到了错误——如果这种情况发生在您身上,请尝试执行Map foo=new HashMap()而不是Map

 类似资料:
  • 由于我在Drools中使用Scala不可变对象,为了更新事实,我需要创建一个新对象来替换它。我已经为要调用的规则编写了一个Scala方法,它只返回这样一个对象。 我的问题是,在Drools规则的“然后”部分中定义新的Scala case类对象的语法是什么?我尝试过类似于以下我在某处看到的语法,但它似乎也没有起到作用...(即使对于标准类型,如字符串) 目前对Drools Scala的支持和文档似乎

  • 问题内容: 我制作了一个便签程序,可以帮助您学习JavaFX。它通过XML保存该类,并在启动时查找XML文件,并将其添加到名为AllCards的NoteCardSet类型的ArrayList,即NoteCards的ArrayList。有了这个,我制作了许多动态按钮,使它们宽了4列。这是该代码: 显然,这可以在JavaFX中创建,但是可以在FXML中创建吗? 问题答案: 不,您不能在FXML中执行此

  • 问题内容: 是否可以在Java中动态创建新变量。 因此,如果两次调用了新方法,是否应该向该类中新添加2个新变量? 可能吗? 问题答案: 否。您是否考虑过在课程中存储“ a ”?映射中的键将是“变量名”,映射中的值将是逻辑变量名。 如果您可以提供有关您要实现的目标的更多信息(从高角度来看),那将有所帮助。

  • Gulp任务定义 问题方案 当我发出时,发生的情况附在下面的日志中。 问题 为什么会这样?(请给我一个深入的解释,因为我正在搜索内部) 为什么gulp stream不能轮询文件是否已创建。 有没有更好的方法来处理这类情况?

  • 我正在将数据写入s3 bucket,并使用pyspark创建parquet文件。我的桶结构如下所示: 子文件夹和表这两个文件夹应该在运行时创建,如果文件夹不存在,如果文件夹存在,则应该在文件夹表中创建拼接文件。 当我在本地计算机上运行pyspark程序时,它会用_$folder$(like)创建额外的文件夹,但是如果在emr上运行相同的程序,它会用_success创建。 是否有办法只在s3中创建文

  • 我也用同样的结果尝试了这个视频中的建议。 最后一件事,我已经没有想法了:在Chrome开发者控制台,我看到创建失败,错误为400,这表明我需要更新白名单URL。我通过添加以下URL实现了这一点: 这个问题一直让我抓狂。我想我什么都试过了。让我想知道我是否需要在Firebase中重新创建我的应用程序。