处理与流口水的1:n关系

时间:2019-05-24 07:16:38

标签: drools

我正在尝试根据另一事实的内容编写适用于一组事实的规则。我已将问题简化为带房间的房子。假设我们有类似的东西:

House(id);
Room(id, houseId, floor, side, paint);

现在,如果我想在所有房间的左侧都以绿色绘制的所有房屋上触发规则,我会写:

rule "Left side 1st floor green"
when
   $h: House()
   forall($r: Room(houseId=$h.id, floor==1, side=="left")
       Room(id == $r.id, paint == "green"))
then
   //Do whatever on rule triggering
end

但是,如果工作存储器中的对象是以这种方式组织的,那该怎么办?

House(id, List<> roomIds);
Room(id, floor, side, paint);

如何为给定房屋的房间写一个foreach条件(或任何其他方法)以进行相同考虑?是有意义的,还是我应该更好地尝试重新组织对象,使关系以另一种方式表达出来?

谢谢

2 个答案:

答案 0 :(得分:0)

根据您的规则,您没有带房间的房屋。根据您的定义,在工作记忆中有房屋,在工作记忆中有房间,然后尝试匹配这些房屋。

为什么您的房屋中没有房间清单?那会更有意义:

House(houseId, List<Room> rooms)
Room(roomId, floor, side, paint)

那么您的规则将是:

rule "Left side 1st floor green"
  when
   $houses : House ($rooms : rooms, $houseId : houseId)
   $room : Room ($roomId : roomId, floor==1 && side=="left" && paint == "green") from $rooms
  then
   //Rule would trigger for each room left side 1st floor green rooms
   System.out.println("House "+$houseId+" has following left side 1st floor green room: "+$roomId);
end

答案 1 :(得分:0)

假设House中的List<> roomIdsRoom.id的列表,那么您可以执行以下操作:

rule "Left side 1st floor green"
when
   $h: House(/* .. conditions for specific house? .. */)
   $r : Room($h.roomIds contains id, floor==1, side=="left", paint == "green")
then
   //Do whatever on rule triggering
end

但是这有点效率不高,我也同意其他人的回答,更改业务/数据模型会使编写这种规则更加习惯和更有效率。例如,如果“房屋”确实具有“房间”列表,则还可以使用OOPath来按需导航结构。