Как убедиться, что ключи сопоставления ключ-значение уникальны в SHACL?
Предположим, мои данные моделируют сопоставление ключ-значение, например, я управляю шикарным отелем и хочу отслеживать заказы моих гостей на каждый прием пищи. Как я могу гарантировать, что для каждого приема пищи я получаю заказ каждого гостя (т.е. все ключи присутствуют), и на каждого гостя у меня есть только один заказ (то есть все ключи уникальны)?
Пример кода для начала работы:
Формы:
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" ] .
Одно из известных мне решений заключается в том, чтобы использовать qualShape и его ограничения minCount и maxCount отдельно для каждого ключа в списке. Однако для больших "гостевых списков" это становится трудно поддерживать. В моей работе у меня есть список из примерно 40 ключей. С 40 блоками операторов qualShape становится непрактичным проверять список (и я уже написал сценарий генерации этих операторов в первую очередь).
Я искал документацию, но не смог найти какой-либо оператор "sh: disjointInScope" или "sh: uniqueFromList", который я хотел (важно, чтобы ограничение не заставляло значение быть уникальным во всем графе данных, поскольку, например, может появиться Джеймс) в несколько порядков). Как получить желаемое поведение в читаемом человеком коде SHACL?
1 ответ
Если я правильно понимаю ваш конкретный сценарий, то это должно привести к нарушению:
ex:MealShape
sh:property [
sh:path ( ex:orders ex:guest ) ;
sh:maxCount 2 ;
sh:minCount 2 ;
] ...
Механизм здесь заключается в том, что выражение пути (ex:orders/ex:guest в нотации SPARQL) используется для указания того, что на каждую еду должно быть ровно два отдельных гостя, что также подразумевает, что каждый из них может быть только частью одного заказа, В сочетании с sh: in это гарантирует, что присутствуют только разрешенные ключи и все они. Однако вам необходимо выровнять длину списка sh: в списке со значениями sh: min / max, поэтому я не уверен, насколько это возможно.
Вероятно, вы можете дополнительно обобщить этот шаблон с помощью SHACL-SPARQL, например, чтобы ввести компоненты ограничений более высокого уровня, о которых вы говорите.