包含 FILTER NOT EXISTS 和 OPTIONAL 的 UNION 案例不会产生结果?
UNION case containing FILTER NOT EXISTS and OPTIONAL doesn't produce results?
我有一个选择某些项目的查询。如果这些项目属于特定的 class (:UserSuitability),那么我需要检查用户是否也来自同一个 class。有四种可能的情况:
- 该项目来自 class,即 rdfs:subClassOf:UserSuitability,用户也来自同一个 class。然后检查该项目是否包含 hasSuitabilityValue 的值并将其分配给变量 ?suitabilityValue.
- 该项目来自 class 即 rdfs:subClassOf :UserSuitability,但用户不是,然后检查该项目是否包含 hasSuitabilityNotValue 的值并将其分配给变量 ?suitabilityValue。
- 该项目不是来自 class 即 rdfs:subClassOf:UserSuitability,然后将 1 分配给变量 ?suitabilityValue。
- 该项目不是来自 class 即 rdfs:subClassOf:UserSuitability,用户也不是。在这种情况下,什么都不做。
到目前为止我的查询以及用于测试它的数据在下面提供。请注意,数据中的 :item1 应匹配并集的左侧,而 :item2 应匹配右侧。右边似乎永远不会匹配。
数据
@prefix : <http://www.semanticrecommender.com/rs#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
:user1 a :class1 .
:user1 :likes :item1 .
:user1 :likes :item2 .
:class1 rdfs:subClassOf :UserSuitability .
:item1 a :class1 .
:item1 :hasSuitabilityWeight 1.5 .
:item1 :hasNotSuitabilityWeight 0.5 .
:item2 a :class2 .
:class2 rdfs:subClassOf :UserSuitability .
查询
prefix : <http://www.semanticrecommender.com/rs#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?item ?suitabilityValue where
{
values ?user {:user1}
?user :likes ?item
optional{
#-- check if the item is from a class that is
#-- rdfs:subClassOf :UserSuitability
?item a ?suitabilityClass.
?suitabilityClass rdfs:subClassOf :UserSuitability.
{
#-- if the user is also from the same class
?user a ?suitabilityClass
optional{
#-- check if the item has a value for :hasSuitabilityWeight
?item :hasSuitabilityWeight ?suitabilityValueOptional.
}
#-- if it does, assign it to the variable
#-- ?suitabilityValue, otherwise, assign 1
#-- to the variable suitabilityValue
bind(if(bound(?suitabilityValueOptional), ?suitabilityValueOptional, 1) as ?suitabilityValue)
}
union
{
#-- if the user is not from the same class
filter not exists {?user a ?suitabilityClass}
optional{
#-- if the item has a value to hasNotSuitabilityWeight
?item :hasNotSuitabilityWeight ?suitabilityNotValueOptional.
}
#-- assign it to suitabilityValue, otherwise, assign 0
bind(if(bound(?suitabilityNotValueOptional), ?suitabilityNotValueOptional, 0) as ?suitabilityValue)
}
}
}
所以,我尝试从头开始重现这个问题,最终得到的数据与您的非常相似,只是稍微简单了一点。这是我最终使用的数据,它让我避免了一些关于 class 是否真的合适的过滤。
@prefix : <urn:ex:>
:user a :A ;
:likes :i , :j .
:i a :A ;
:hasValueYes 1 ;
:hasValueNo 2 .
:j a :B .
现在,这是类似于您的查询;它只会得到两个项目之一的结果,即使看起来另一个应该匹配。有一个注释行,我稍后会解释。
prefix : <urn:ex:>
select ?item ?value {
values ?user { :user }
?user :likes ?item .
?item a ?itemClass .
{
?user a ?itemClass
optional {
?item :hasValueYes ?valueYes
}
bind(if(bound(?valueYes), ?valueYes, "default yes value") as ?value)
}
union
{
#-- ?item ?anyP ?anyO # (***)
filter not exists { ?user a ?itemClass }
optional {
?item :hasValueNo ?valueNo
}
bind(if(bound(?valueNo), ?valueNo, "default no value") as ?value)
}
}
----------------
| item | value |
================
| :i | 1 |
----------------
现在,该查询中有一行注释:
#-- ?item ?anyP ?anyO # (***)
如果您取消注释该行,您将得到预期的结果:
-----------------------------
| item | value |
=============================
| :i | 1 |
| :j | "default no value" |
-----------------------------
我认为这里发生的是在第二种可选情况下,因为没有引入绑定的三重模式(因为可选 不匹配),union 的那一边没有被包括在内,即使 bind 如果允许边匹配,将引入一些绑定。通过添加模式:
?item ?anyP ?anyO
对于查询,至少有 something 将在 union 的那部分匹配,此时其余部分块被包括在内。我使用 ?anyP 和 ?anyO 来强调它是任意的,但是因为你已经知道 ?item 是一个 ?itemClass,你可以再次包含那个三元组,即 ?item a ?itemClass.
所以,在你的情况下,如果你只添加
?user :likes ?item
右边的 union 块,你会得到你期待的结果:
-----------------------------
| item | suitabilityValue |
=============================
| :item2 | 0 |
| :item1 | 1.5 |
-----------------------------
我有一个选择某些项目的查询。如果这些项目属于特定的 class (:UserSuitability),那么我需要检查用户是否也来自同一个 class。有四种可能的情况:
- 该项目来自 class,即 rdfs:subClassOf:UserSuitability,用户也来自同一个 class。然后检查该项目是否包含 hasSuitabilityValue 的值并将其分配给变量 ?suitabilityValue.
- 该项目来自 class 即 rdfs:subClassOf :UserSuitability,但用户不是,然后检查该项目是否包含 hasSuitabilityNotValue 的值并将其分配给变量 ?suitabilityValue。
- 该项目不是来自 class 即 rdfs:subClassOf:UserSuitability,然后将 1 分配给变量 ?suitabilityValue。
- 该项目不是来自 class 即 rdfs:subClassOf:UserSuitability,用户也不是。在这种情况下,什么都不做。
到目前为止我的查询以及用于测试它的数据在下面提供。请注意,数据中的 :item1 应匹配并集的左侧,而 :item2 应匹配右侧。右边似乎永远不会匹配。
数据
@prefix : <http://www.semanticrecommender.com/rs#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
:user1 a :class1 .
:user1 :likes :item1 .
:user1 :likes :item2 .
:class1 rdfs:subClassOf :UserSuitability .
:item1 a :class1 .
:item1 :hasSuitabilityWeight 1.5 .
:item1 :hasNotSuitabilityWeight 0.5 .
:item2 a :class2 .
:class2 rdfs:subClassOf :UserSuitability .
查询
prefix : <http://www.semanticrecommender.com/rs#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?item ?suitabilityValue where
{
values ?user {:user1}
?user :likes ?item
optional{
#-- check if the item is from a class that is
#-- rdfs:subClassOf :UserSuitability
?item a ?suitabilityClass.
?suitabilityClass rdfs:subClassOf :UserSuitability.
{
#-- if the user is also from the same class
?user a ?suitabilityClass
optional{
#-- check if the item has a value for :hasSuitabilityWeight
?item :hasSuitabilityWeight ?suitabilityValueOptional.
}
#-- if it does, assign it to the variable
#-- ?suitabilityValue, otherwise, assign 1
#-- to the variable suitabilityValue
bind(if(bound(?suitabilityValueOptional), ?suitabilityValueOptional, 1) as ?suitabilityValue)
}
union
{
#-- if the user is not from the same class
filter not exists {?user a ?suitabilityClass}
optional{
#-- if the item has a value to hasNotSuitabilityWeight
?item :hasNotSuitabilityWeight ?suitabilityNotValueOptional.
}
#-- assign it to suitabilityValue, otherwise, assign 0
bind(if(bound(?suitabilityNotValueOptional), ?suitabilityNotValueOptional, 0) as ?suitabilityValue)
}
}
}
所以,我尝试从头开始重现这个问题,最终得到的数据与您的非常相似,只是稍微简单了一点。这是我最终使用的数据,它让我避免了一些关于 class 是否真的合适的过滤。
@prefix : <urn:ex:>
:user a :A ;
:likes :i , :j .
:i a :A ;
:hasValueYes 1 ;
:hasValueNo 2 .
:j a :B .
现在,这是类似于您的查询;它只会得到两个项目之一的结果,即使看起来另一个应该匹配。有一个注释行,我稍后会解释。
prefix : <urn:ex:>
select ?item ?value {
values ?user { :user }
?user :likes ?item .
?item a ?itemClass .
{
?user a ?itemClass
optional {
?item :hasValueYes ?valueYes
}
bind(if(bound(?valueYes), ?valueYes, "default yes value") as ?value)
}
union
{
#-- ?item ?anyP ?anyO # (***)
filter not exists { ?user a ?itemClass }
optional {
?item :hasValueNo ?valueNo
}
bind(if(bound(?valueNo), ?valueNo, "default no value") as ?value)
}
}
----------------
| item | value |
================
| :i | 1 |
----------------
现在,该查询中有一行注释:
#-- ?item ?anyP ?anyO # (***)
如果您取消注释该行,您将得到预期的结果:
-----------------------------
| item | value |
=============================
| :i | 1 |
| :j | "default no value" |
-----------------------------
我认为这里发生的是在第二种可选情况下,因为没有引入绑定的三重模式(因为可选 不匹配),union 的那一边没有被包括在内,即使 bind 如果允许边匹配,将引入一些绑定。通过添加模式:
?item ?anyP ?anyO
对于查询,至少有 something 将在 union 的那部分匹配,此时其余部分块被包括在内。我使用 ?anyP 和 ?anyO 来强调它是任意的,但是因为你已经知道 ?item 是一个 ?itemClass,你可以再次包含那个三元组,即 ?item a ?itemClass.
所以,在你的情况下,如果你只添加
?user :likes ?item
右边的 union 块,你会得到你期待的结果:
-----------------------------
| item | suitabilityValue |
=============================
| :item2 | 0 |
| :item1 | 1.5 |
-----------------------------