假设我的数据对键值映射进行建模,例如,我经营一家高档酒店,并希望跟踪客人每顿饭的订单。我如何确保每顿饭我都得到每位客人的订单(即所有钥匙都在场)并且每位客人我只有一份订单(即所有钥匙都是唯一的)?
让我们开始的示例代码:
形状:
ex:MealShape
a sh:NodeShape ;
sh:targetClass ex:Meal ;
sh:property [
sh:path ex:orders ;
sh:minCount 2 ;
sh:maxCount 2 ;
sh:node ex:OrderShape ;
] .
ex:OrderShape
a sh:NodeShape ;
sh:targetClass ex:Order ;
sh:property [
sh:path ex:guest ;
# The guest list! Code maintenance should happen here.
sh:in ( "James" "Margaret" ) ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ex:order ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
数据:
## Guests
ex:james ex:name "James" .
ex:margaret ex:name "Margaret" .
## Meals
### Valid meal
ex:breakfast
a ex:Meal ;
ex:orders [ ex:guest "James" ; ex:order "Eggs" ] ;
ex:orders [ ex:guest "Margaret" ; ex:order "Cereal" ] .
### DESIRED TO BE invalid meal
### currently does not cause a validation result
ex:lunch
a ex:Meal ;
ex:orders [ ex:guest "James" ; ex:order "Salad" ] ;
# Problem: James placed two orders, Maggie placed zero
ex:orders [ ex:guest "James" ; ex:order "Burger" ] .
我知道的一种解决方案是对列表中的每个键分别使用qualifiedShape 及其minCount 和maxCount 约束。然而,对于较大的“客人名单”,这变得难以维护。在我的工作中,我有一个大约 40 个键的列表。使用 40 块qualifiedShape 语句,检查列表变得不切实际(而且我已经首先编写了这些语句的生成脚本)。
我已经搜索了文档,但找不到我想要的一种“sh:disjointInScope”或“sh:uniqueFromList”语句(至关重要的是,约束不应强制该值在整个数据图中是唯一的,因为例如 James 可能会出现在几个订单中)。如何在人类可读的 SHACL 代码中获得所需的行为?