Условный подзапрос в функции SPIN (SPARQL)
Как изменить формулу запроса в зависимости от того, связана ли переменная?
Я использую магическое свойство так:
WHERE {
VALUES (?subj) {
([my bound positional parameter value goes here...])
}
?subj :myMagicProperty ?result .
}
Внутри волшебного свойства я делаю союз:
?result a :Rule .
{
?result :someProp ?subj .
}
UNION
{
FILTER NOT EXISTS {
?result :someProp ?anyValue .
}
}
Другими словами, принеси мне все результаты, где :someProp
это значение или :someProp
не определено.
Здесь самая сложная часть. Если ?subj
не связан (то есть, я установил его как UNDEF
в VALUES
блок), приведенный выше запрос сходит с ума и возвращает все.
Вместо этого я хочу проверить, если ?subj
не связан. Если ?subj
не связан, :myMagicProperty
должен возвращать только следующие результаты:
FILTER NOT EXISTS {
?result ?someProp ?anyValue .
}
Я экспериментировал с использованием FILTER
и BOUND
функции, но я не могу понять, как получить правильное поведение. Как я могу бросить один из UNION
пункты из моего запроса, когда ?subj
не связан?
Обновления
Пересмотрел первый запрос, чтобы добавить VALUES
блок.
Добавлено недостающее ?result a :Rule .
заявление.
Исправленный ?someProp
в :someProp
,
3 ответа
Хитрость в том, что мне нужно сделать UNION, используя переменную, отличную от той, которая передана в качестве аргумента. Таким образом, операция UNION не приводит к привязке несвязанного параметра. После UNION я могу использовать ФИЛЬТР для управления результатами на основе входного параметра.
SELECT ?result
WHERE {
?result a :Rule .
{
SELECT ?rule ?value ?anyValueMatch
WHERE {
{
?rule :someProp ?value .
BIND (false AS ?anyValueMatch) .
}
UNION
{
FILTER NOT EXISTS {
?rule :someProp ?any .
} .
BIND (true AS ?anyValueMatch) .
} .
}
} .
FILTER ((bound(?subj) && (?value = ?subj)) || (?anyValueMatch = true)) .
}
Еще один способ сделать это с помощью COALESCE:
SELECT ?result
WHERE {
?result a :Rule .
OPTIONAL {
?result :someProp ?value .
}
FILTER (COALESCE(?value = ?subj, !bound(?value)))
}
... это исключает выборочный выбор и просто фильтрует включение только совпадений?result, где '?value =?subj', а если это предложение не выполняется, предложение!bound() гарантирует совпадения, которые не имеют свойства:someProp также включены.
Сначала я хотел бы подтвердить ваше намерение. Я хотел бы сделать это, попросив вас ответить на следующий запрос, который вы можете запустить в TopBraid Composer.
SELECT *
WHERE { GRAPH <http://topbraid.org/examples/kennedys> {
VALUES (?property) {(kennedys:firstName) (kennedys:lastName) (UNDEF)}
{
FILTER(BOUND(?property) )
?s ?property ?result .
}
UNION
{
FILTER(!BOUND(?property))
BIND("not sure what you want to do in this case" AS ?result)
}
}
}
Разница в приведенном выше коде по отношению к вашему коду заключается в том, что я устанавливаю значения вашего "someProp" в операторе "VALUES", а вы настраиваете "subj".
UNIONed подграфы используют BOUND и!BOUND в качестве охраны.
Прежде чем идти дальше с помощью, я хотел бы услышать от вас более четкое объяснение запроса, который вы хотите построить. Тогда я могу показать вам магическое свойство, которое будет необходимо.
Это часть вашего первоначального поста, мне нужно понять больше:
Здесь самая сложная часть. Если? Subj не связан (т. Е. Я установил его как UNDEF в блоке VALUES), приведенный выше запрос обнуляется и возвращает все.
Вместо этого я хочу проверить, является ли? Subj несвязанным. Если? Subj не связан, myMagicProperty должен возвращать только следующие результаты:
FILTER NOT EXISTS {
?result ?someProp ?anyValue .
}*
С "someProp undefined", а также "result" и "anyValue", что вы ожидали вернуться? Также у этого вашего подграфа нет утверждений, которые будут заполнять граф и, следовательно, ничего не будут возвращать.
Ральф