2015-10-12 9 views
1

Как изменить формулу запроса в зависимости от того, связана ли переменная?Условный подзапрос в функции 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.

ответ

1

Прежде всего, я хотел бы подтвердить, каковы ваши намерения. Я хотел бы сделать это, попросив вас ответить на следующий запрос, который вы можете запустить в 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 неопределенными, а также результат и anyValue то, что вы ожидали вернуться?? Также у вашего подграфа нет утверждений, которые будут заполнять граф и, следовательно, ничего не вернут.


Ральф

+0

Ralph, Я обновил свое определение магии в вопросе, чтобы добавить термин, отсутствующий в примере кода. Цель состоит в том, что «с учетом некоторого значения? Subj для всех ресурсов Rule найдите правила, которые имеют правило .someProp == subj OR rule.someProp == null (свойство не определено). Если входное значение? Subj равно null, return only Rules, где rule.someProp == null. " – RMorrisey

+0

Я попытался использовать что-то вроде «FILTER (BOUND (? Property))», но я обнаружил, что свойство «свойство» связано с инструкцией, приведенной ниже, в том же блоке, поэтому он не отфильтровывает результаты таким образом Я хочу их. – RMorrisey

1

Хитрость заключается в том, что мне нужно сделать в UNION используя переменную другой, чем тот, переданный в качестве аргумента. Таким образом, операция UNION не приводит к привязке несвязанного параметра. После UNION я могу использовать FILTER для управления результатами на основе входного параметра.

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)) . 
} 
1

Другой способ сделать это с COALESCE: «? Значение = Subj»

SELECT ?result 
WHERE { 
    ?result a :Rule . 
    OPTIONAL { 
     ?result :someProp ?value . 
    } 
    FILTER (COALESCE(?value = ?subj, !bound(?value))) 
} 

... это позволяет избежать суб-выбора и просто фильтрует включать только результат матча, где , и если это предложение не выполняется, предложение! bound() гарантирует совпадения, которые не имеют свойства: someProp.