如何解决使用drools验证具有嵌套地图的事实
我有一个 Fact
类,它是一个 extends java.util.HashMap
类。我将这个类的对象作为事实传递给流口水。
现在一个事实实例看起来像这样 (Map
{
"key1": "value"
"attributes": [{"name": "name1","value": "value1"},{"name": "name2","value": "value2"},{"name": "name3","value": "value3"}...]
"locks": [{"type": "type1","value": "value1","attributes": {"key_a1": "val_a1""key_a2": "val_a2"...}}]
}
在此映射中的根级别条目上运行验证很简单,例如在 key1
上运行验证。
现在,我想对 attributes
和 locks
运行一些验证。
对于属性,我想确保此映射中存在所需的所有属性,并且它们对应的值是正确的。所以我在 when 块中这样做:
fact: Fact(this["key1"] != null && this.containsKey("attributes"));
attributesEntries: Entry(key == "attributes") from fact.entrySet();
attributesMaps: LinkedHashMap() from attributesEntries;
事实是HashMap
属性属于 ArrayList<LinkedHashMap<String,String>>
类型(还为 id
添加了 LinkedHashMap
键,其值仅是键名的值)。
锁属于 ArrayList<LinkedHashMap<String,Object>>
类型
锁具有 Map
但它不起作用。当我评估 attributesEntries
时,它是 ArrayList<LinkedHashMap>
并且它具有所有预期值,但 attributesMaps
为空。我也尝试过传递像 LinkedHashMap(key == 'key1',value == 'val1')
这样的过滤器,但这也不起作用。试图寻找解决方案,但没有一种适用于这种结构。无论有什么可用的,我都试图扩展,但没有奏效。
这是否可能实现,如果可以,如何实现?此外,一旦我能够从 Map
中获取值,我该如何验证它(非空且匹配模式)。
我是 drools 的新手,我们使用的是 5.4.0.Final 版本的 drools。
此外,我如何使用 Map
中的下一层嵌套 locks
。
解决方法
我曾经不幸在一个项目中工作,我们犯了同样的错误并让我们的类扩展了 HashMap。 (公平警告:HashMap 不能很好地序列化,因此您将使用大量额外内存。)
由于您忽略了共享类定义本身,因此我将对您的模型进行一些假设。
但我将根据您的示例 JSON 假设以下内容:
- 您添加了一个带有键“key1”的字符串值(“value”)
- 您使用“locks”键添加了一个
List<Map<String,?>>
值(可能是List<Fact>
) - 您添加了一个带有键“属性”的
List<Map<String,?>>
值(可能是List<Fact>
)
HashMap 的 get(key)
方法会返回一个对象值;您已经注意到特殊的 this[ key ]
语法。
从您的部分规则尝试来看,并不完全清楚您要做什么。我认为您正在尝试获取保存在地图中“属性”键下的 List<Map<String,?>>
。
rule "Do something with the attributes"
when
$fact: Fact( this["key1"] != null,$attr: this["attributes"] != null )
then
System.out.println("Found " + $attr.size() + " attributes");
end
this["attributes"]
返回与键属性关联的值。在这种情况下,它是一个 List 或任何你塞进去的东西。如果键不存在,则空检查处理。
您还询问了如何使用其中一个列表中的子地图进行操作。假设想要对具有 "name": "name1"
...
rule "Do something with the 'name = name1' attribute"
when
$fact: Fact( this["key1"] != null,$attributes: this["attributes"] != null )
$nameAttr: Map( this["name"] == "name1" ) from $attributes
then
// do something with $nameAttr
end
当然,这种模式会重复。假设您已将另一个 List<Map<String,?>>
推入您的属性映射:
rule "Do something with a child of 'name' attribute"
when
$fact: Fact( this["key1"] != null,$attributes: this["attributes"] != null )
$nameAttr: Map( this["name"] == "name1",$attrKids: this["children"] != null ) from $attributes
$childNameAttr: Map( this["name"] == "child1" ) from $attrKids
then
// etc.
end
我强烈建议您重新考虑您的对象模型,使其不基于 Map。在我工作的公司,我们所有的项目都是针对嵌套的基于 Map 的模型构建的,并运行 Drools 5.0.1,我花了大量的时间和精力将其中的一部分升级到 Drools 7 和一个只传递数据的正确模型我们需要。它节省了吨的资源,最终速度更快。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。