【问题标题】:Duplicate pojo validation rule in droolsdrools中重复的pojo验证规则
【发布时间】:2021-09-30 13:40:52
【问题描述】:

我在 kiesession 中插入了大约 1000 个 A 类型的 pojo,如果在 kiesession 中 A 存在重复的 pojo,我如何在 drools 中添加规则来执行某些任务。

class A {
     private int someInt;
     private String someString;
}

function boolean checkDuplicate(List input) {
    int a = input.size();
    int b = ((List) input.stream().distinct().collect(Collectors.toList())).size();
    return a!=b;
}

dialect "java"
rule "ADuplicateRule"
   when
        $input : List( ) from collect(A())
        eval(checkDuplicate($input))
   then
        throw new Exception("A list has duplicate values");
end

上述方法可行,但有更好更简单的方法来实现吗?

喜欢在 kiesession 中对 pojo 字段的总和进行验证,我们可以简单地写这个

$sumSomeInt: Integer(this > 90) from accumulate(A( $SomeInt: someInt ), sum($SomeInt))

是否可以在类似的行上做一些事情来检查重复项?

【问题讨论】:

  • 传统上,POJO 的值相等可以通过 hashcode 的投影来近似,因此在 HashSet 中收集所有以前看到的 hashCode 可能对你有用。注意事项 - 发生碰撞的可能性很小,因此您可能会误报。此外,您可能需要应用时间或计数窗口来防止哈希集无限期膨胀。
  • 在您的情况下,是否可以在早期删除重复项而不处理“坏数据”?

标签: drools rule-engine


【解决方案1】:

你已经很接近了:

rule "Duplicates Found"
when
  A( $i: someInt, $s: someString )
  List( size > 1 ) from collect( A( someInt == $i, someString == $s ) )
then 
  // handle the duplicate case
end

根据需要调整您的平等检查。我建议不要在“then”中抛出异常。

或者,您甚至不需要收集完整的重复列表;至少存在一个副本就足够了。这使您的规则更像这样:

rule "Duplicates found - v2"
when
  $a: A( $i: someInt, $s: someString )
  exists( A( this != $a, someInt == $i, someString == $s ))
then
  // handle the duplicates case
end

在这些规则中,我们利用了 Drools 会隐式检查工作内存中 A 的所有实例这一事实。所以在第一条规则中,对于每个A,它会检查该实例是否存在重复;如果有,规则触发。否则,它会检查 A 的下一个实例,依此类推,直到所有 A 实例都被求值。

第二条规则依赖于相同类型的工作流,但还包括对exists 子句的this != $a 检查,以验证我们发现的“重复”实际上不是我们正在检查的实例。由于第一条规则仅针对List( size > 1 ) 触发,因此它预计我们正在检查的实例将包含在collect 的结果中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 1970-01-01
    相关资源
    最近更新 更多