SHACL для сравнения значений на двух разных узлах?
Я пытаюсь написать ограничение SHACL для сравнения дат, где начальная дата должна быть меньше или равна конечной дате. Когда даты прикрепляются к одному и тому же узлу с помощью :beginDate
а также :endDate
предикаты, ограничение прямо вперед:
:StartEndRuleShape a :PropertyShape ;
sh:path :beginDate ;
sh:lessThanOrEquals :endDate ;
sh:message "Begin Date is after End Date." .
Модель реального мира более сложна. На прилагаемой диаграмме обратите внимание, как :AnimalSubject
hasReferenceInterval
, ReferenceInterval IRI имеют :ReferenceBegin
и :ReferenceEnd
которым в свою очередь присваивается значение даты с использованием time:inXSDDate
сказуемое. Как я могу применить ограничение в этом случае, чтобы убедиться, что значение ReferenceBegin равно или меньше значения ReferenceEnd? Это случай для использования SHACL-SPARQL или sequencePath? Я не смог найти хороших примеров ни того, ни другого. Ура!
Я протестировал следующий SHACL-SPARQL на данных, которые нарушают ограничение: ReferenceBegin = "2016-12-07", ReferenceEnd = "2016-12-06", но отчет о проверке не обнаруживает нарушения. Если я запускаю SPARQL самостоятельно, он выбирает наблюдение. Есть мысли о том, почему? Я использую Stardog/Stardog Studio и также разместил на своей платформе поддержки пользователей.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix time: <http://www.w3.org/2006/time#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix : <http://foo.bar.org/> .
:IntervalShape a sh:NodeShape ;
sh:targetClass :ReferenceInterval ;
sh:sparql [
a sh:SPARQLConstraint ;
sh:message "End Date must be greater than or equal to Begin Date";
sh:prefixes [
sh:declare [
sh:prefix "time" ;
sh:namespace "http://www.w3.org/2006/time#"^^xsd:anyURI ;
]
] ;
sh:select
"""SELECT $this (?beginDate AS ?intervalStart) (?endDate AS ?intervalEnd)
WHERE {
$this :hasReferenceInterval ?interval .
?interval :ReferenceBegin ?beginIRI ;
:ReferenceEnd ?endIRI .
?beginIRI time:inXSDDate ?beginDate .
?endIRI time:inXSDDate ?endDate .
FILTER (! (?endDate >= ?beginDate ))
}""" ;
] .
1 ответ
Похоже, у вашего ограничения есть две проблемы:
Вы объявляете
time
префикс в вашем SHACL, но неbase
префикс. Ты хочешь:sh:prefixes [ sh:declare [ sh:prefix "time" ; sh:namespace "http://www.w3.org/2006/time#"^^xsd:anyURI ; ], [ sh:prefix "" ; sh:namespace "http://foo.bar.org/"^^xsd:anyURI ; ] ] ;
Ваш фокусный узел
:ReferenceInterval
Однако способ написания вашего запроса,$this
будет когда-либо связан только с сущностями, которые:hasReferenceInterval [a :ReferenceInterval]
, Я переписал запрос так, чтобы?interval
сейчас$this
следующее:sh:select """SELECT $this (?beginDate AS ?intervalStart) (?endDate AS ?intervalEnd) WHERE { $this :ReferenceBegin ?beginIRI ; :ReferenceEnd ?endIRI . ?beginIRI time:inXSDDate ?beginDate . ?endIRI time:inXSDDate ?endDate . FILTER (! (?endDate >= ?beginDate )) }""" ;
Добавив это ограничение, я смог увидеть нарушение.