简体   繁体   English

流口水基于时间的限制和“现在”

[英]drools time based constraints and “now”

We are trying to write a drool which says something like "If the event happened in the last week, execute the consequence". 我们正在尝试写流口水,上面写着“如果事件在上周发生,请执行结果”。 We have regular java date objects representing the time the event happened, but we aren't sure how to express in the LHS of a drool that we want that date object to have taken place in the last week. 我们有常规的Java日期对象来表示事件发生的时间,但是我们不确定如何在流口水的LHS中表示我们希望该日期对象在上周发生。 Importantly, the timespan of a week is arbitrary. 重要的是,一周的时间是任意的。 It could change to month or year at any time. 它可以随时更改为月或年。 Finally, keep in mind that our session is stateful. 最后,请记住我们的会议是有状态的。

I found a somewhat related question here: use java.util.Date in a rule's LHS . 我在这里找到了一个相关的问题: 在规则的LHS中使用java.util.Date I will quote the most relevant excerpt from the answer below: 我将从以下答案中引用最相关的摘录:

If you are executing within a stateless session, then your approach will work in combination with the Fusion operators. 如果您在无状态会话中执行,那么您的方法将与Fusion运算符结合使用。 It is still not a recommended practice, however. 但是,仍然不建议这样做。 A better approach is to define a fact, call it Now, which contains a single Date field. 更好的方法是定义一个事实,将其称为Now(立即),其中包含一个Date(日期)字段。 Initialize and insert it along with your other facts then reason against it instead of a global. 初始化并与其他事实一起插入它,然后针对它而不是全局原因进行推理。

If you have a stateful session, it gets more tricky because real time is passing even while the session is idle, meaning your Now fact is getting more and more out of date. 如果您有状态的会话,那么它将变得更加棘手,因为即使会话处于空闲状态,实时时间也会过去,这意味着您的Now事实越来越过时了。 The way we have solved this is via the use of a WorkingMemoryEventListener. 我们解决此问题的方法是使用WorkingMemoryEventListener。 We use the objectInserted, objectRetracted, and objectUpdated methods of this listener to keep our Now fact current (we do not care about precision less than one minute so we check whether a minute has passed from the last update to avoid unnecessary overhead). 我们使用此侦听器的objectInserted,objectRetracted和objectUpdated方法来使我们的Now事实保持最新(我们不在乎不到一分钟的精度,因此我们检查从上一次更新起是否经过一分钟以避免不必要的开销)。 Rules won't evaluate if working memory isn't changing, so using this listener is sufficient to ensure that Now is updated when it needs to be (unless you have queries that depend on the current value of Now, but that's another topic). 规则不会评估工作内存是否没有更改,因此使用此侦听器足以确保在需要时立即更新Now(除非您的查询依赖于Now的当前值,但这是另一个主题)。

In the answer, the author describes problems with the representation of "now". 在回答中,作者描述了“现在”表示的问题。 His solution seems hacky and the answer was posted in a much earlier version of drools. 他的解决方案似乎很笨拙,答案发布在更早的版本中。 I'm making a new question here to give better attention to this question specifically rather than the passing treatment it gets in the one I linked. 我在这里提出一个新问题,以便更具体地关注此问题,而不是在我所链接的问题中获得通过的待遇。

UPDATE: 更新:

Timestamps are the simple java.util.Date object. 时间戳是简单的java.util.Date对象。

Events are added to the session via api call. 通过api调用将事件添加到会话中。 The stateful session is an object held by a java based api. 有状态会话是由基于Java的api持有的对象。 The api adds events to the knowledge session when they are submitted. api在事件提交后将其添加到知识会话。 FireAllRules occurs about once per second. FireAllRules大约每秒发生一次。

The fundamental question (as so often) is what the requirement really means. 基本问题(通常如此)是需求的真正含义。 An event "happening in the last week" could be anything happening 7*24*60*60 seconds ago; 事件“发生在上周”可能是7 * 24 * 60 * 60秒前发生的任何事情; it could be something that has happened from Monday 20151228 up to now, or from Sunday 20151227 until now, or maybe something similar where just the date matters and not the time of the day. 可能是从20151228星期一到现在,或者从20151227星期日到现在发生了,或者可能只是日期很重要,而不是一天中的时间。

Ask what it really means, and rephrase your question accordingly. 询问其真正含义,然后相应地改写您的问题。

If you do need a sliding window, going back from "now", ie, verily this moment, for a certain time interval (of w seconds), you still need to define the speed and accuracy with which this check has to be performed. 如果确实需要一个滑动窗口,请从“现在”返回,即恰好是这一刻,在一定的时间间隔( w秒)内,您仍需要定义执行此检查的速度和准确性。 Drools does not have a continually updated notion of "now" in its absolute sense. 从绝对意义上讲,Drools并没有不断更新“现在”的概念。 It is possible to create and maintain a fact representing an approximation of "now", using a timer (which is preferable to using a listener). 使用计时器(可能比使用侦听器更好)可以创建和维护一个表示“现在”的近似值的事实。 The Now-fact has to be updated periodically, every d seconds. 事实必须每d秒定期更新一次。 If you insert a new event with a time stamp after the last update of Now, it will not be recognized for up to d seconds. 如果您在最后一次更新即时之后插入带有时间戳的新事件,则最多d秒将无法识别该事件。 (And if you insert a new event with a time stamp between w and w + d seconds in the past, it is possible that it triggers the rule.) (并且,如果您插入一个新事件,该事件的时间戳在过去的ww + d秒之间,则有可能触发该规则。)

Since you haven't indicated how you insert events and how their time stamps are implemented I cannot provide rules illustrating what I have outlined. 由于您尚未指出如何插入事件以及如何实现事件的时间戳,因此我无法提供规则说明我所概述的内容。 See the Drools documentation about "Timers and Calendars". 请参阅有关“计时器和日历”的Drools文档。

Edit 编辑

What has not been said in the question is the relation of an event's time (ie, when it really happened in the real world) and its timestamp (ie, when it was entered into Working Memory). 问题中没有说的是事件的时间 (即事件在现实世界中真正发生的时间 )与其时间戳 (即事件被输入到工作记忆中)之间的关系。 Rules checking for an events timestamp being in the last week or month or second are futile: this will be invariably true. 检查事件时间戳记在最后一周,一个月或第二秒的规则是徒劳的:这将始终是正确的。

If you call fireAllRules repeatedly, updating the time horizon with a timestamp 1 week (month,...) back before the call is one simple way. 如果您反复调用fireAllRules,则在调用之前回溯1周(月,...)的时间戳来更新时间范围是一种简单的方法。 Or update Now before each call. 或在每次通话前立即更新。 Both is far from "hacky". 两者都不是“ hacky”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM