我们正在尝试写流口水,上面写着“如果事件在上周发生,请执行结果”。我们有常规的Java日期对象来表示事件发生的时间,但是我们不确定如何在流口水的LHS中表示我们希望该日期对象在上周发生。重要的是,一周的时间是任意的。它可以随时更改为月或年。最后,请记住,我们的会议是有状态的。
我在这里找到了一个相关的问题:在规则的LHS中使用java.util.Date。我将从以下答案中引用最相关的摘录:
如果您在无状态会话中执行,那么您的方法将与Fusion运算符结合使用。但是,仍然不建议这样做。更好的方法是定义一个事实,将其称为Now(立即),其中包含一个Date(日期)字段。初始化并与其他事实一起插入它,然后针对它而不是全局原因进行推理。 如果您有状态的会话,那么它将变得更加棘手,因为即使会话处于空闲状态,实时时间也会过去,这意味着您的Now事实越来越过时了。解决问题的方法是使用WorkingMemoryEventListener。我们使用此侦听器的objectInserted,objectRetracted和objectUpdated方法来保持Now事实为最新(我们不关心精度是否低于一分钟,因此我们检查距上一次更新是否已经过一分钟以避免不必要的开销)。规则不会评估工作内存是否没有更改,因此使用此侦听器足以确保在需要时立即更新Now(除非您的查询依赖于Now的当前值,但这是另一个主题)。
如果您在无状态会话中执行,那么您的方法将与Fusion运算符结合使用。但是,仍然不建议这样做。更好的方法是定义一个事实,将其称为Now(立即),其中包含一个Date(日期)字段。初始化并与其他事实一起插入它,然后针对它而不是全局原因进行推理。
如果您有状态的会话,那么它将变得更加棘手,因为即使会话处于空闲状态,实时时间也会过去,这意味着您的Now事实越来越过时了。解决问题的方法是使用WorkingMemoryEventListener。我们使用此侦听器的objectInserted,objectRetracted和objectUpdated方法来保持Now事实为最新(我们不关心精度是否低于一分钟,因此我们检查距上一次更新是否已经过一分钟以避免不必要的开销)。规则不会评估工作内存是否没有更改,因此使用此侦听器足以确保在需要时立即更新Now(除非您的查询依赖于Now的当前值,但这是另一个主题)。
在回答中,作者描述了“现在”表示的问题。他的解决方案似乎不可靠,答案发布在更早的版本中。我在这里提出一个新问题,以便更具体地关注此问题,而不是在我链接的问题中获得通过的待遇。
更新:
时间戳是简单的java.util.Date对象。
通过api调用将事件添加到会话中。有状态会话是由基于Java的api持有的对象。api在事件提交后将其添加到知识会话。FireAllRules大约每秒发生一次。
基本问题(通常如此)是需求的 真正 含义。“上周发生”事件可能是7 * 24 * 60 * 60秒前发生的任何事情;从20151228星期一到现在,或者从20151227星期日到现在,这可能是发生的事情,或者可能只是日期很重要,而不是一天中的时间。
询问其真正含义,然后相应地改写您的问题。
如果确实需要一个滑动窗口,请从“现在”返回,即恰好是这一刻,在一定的时间间隔( w 秒)内,您仍然需要定义必须执行此检查的速度和准确性。 从绝对意义上讲,Drools并没有不断更新“现在”的概念。 使用计时器(可能比使用侦听器更好)可以创建和维护代表“现在” 近似值 的事实。事实必须每 d 秒定期更新一次。如果您在最后一次更新Now 之后 插入带有时间戳的新事件,则最多 d 秒将无法识别该事件。(如果您插入的新事件的时间戳为 __过去的 w 和 w + d 秒,则有可能触发规则。)
由于您尚未指出如何插入事件以及如何实现事件的时间戳,因此我无法提供规则说明我所概述的内容。请参阅Drools文档中有关“计时器和日历”的信息。
编辑
问题中没有说的是事件的 时间 (即事件在现实世界中真正发生的 时间 )与其 时间戳 (即事件被输入到工作记忆中)之间的关系。检查事件 时间戳记 在上周,上个月或第二秒的规则是徒劳的:这将始终是正确的。
如果您反复调用fireAllRules,则在调用之前回溯1周(月,…)的时间戳来更新时间范围是一种简单的方法。或在每次通话前立即更新。两者都不是“hacky”。