Я пытаюсь написать ограничение SHACL для сравнения дат, где дата начала должна быть меньше или равна дате окончания. Когда даты присоединяются к одному и тому же узлу с помощью предикатов :beginDate
и :endDate
, ограничение является прямым:
:StartEndRuleShape a :PropertyShape ;
sh:path :beginDate ;
sh:lessThanOrEquals :endDate ;
sh:message "Begin Date is after End Date." .
Модель реального мира более сложна. На прилагаемой диаграмме обратите внимание на то, как :AnimalSubject
hasReferenceInterval
. IRI ReferenceInterval имеют :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 ))
}""" ;
] .
Согласен, Хольгер. Я попробовал этот SHACL-SPARQL, но он не обнаруживает нарушения в записи, где я установил ReferenceBegin «2017-12-07» и ReferenceEnd «2017-12-06». Я обновлю свой пост с SHACL-SPARQL.
Похоже, у вашего ограничения есть две проблемы:
Вы объявляете префикс 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 ))
}""" ;
Добавив это ограничение, я смог увидеть нарушение.
Не полный ответ, но для меня это звучит как SHACL-SPARQL. Даже если значения можно получить с помощью выражения пути, значения sh:lessThanOrEquals могут быть только простыми свойствами, а не путями.