1

変数がバインドされているかどうかに基づいてクエリ式を変更するにはどうすればよいですか?

次のように魔法のプロパティを呼び出しています。

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場合、クエリから句の 1 つを削除するにはどうすればよいですか??subj

アップデート

VALUESブロックを追加するために最初のクエリを修正しました。
不足している?result a :Rule .ステートメントを追加しました。に
訂正。?someProp:someProp

4

3 に答える 3

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)) .
}
于 2015-10-13T20:39:40.133 に答える
1

これを行う別の方法は、COALESCE を使用することです。

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

...これにより、副選択が回避され、'?value = ?subj' である ?result 一致のみが含まれるように単純にフィルター処理されます。も含まれています。

于 2016-02-18T04:24:06.453 に答える