This is a question about why my code is not working, not about how to do something, that's why I didn't provide you with a data, but if you want, i can give you, but the data will be my relatively small ontology.
this is my code
OPTIONAL
{
VALUES ?user { rs:ania }
?userContext rdf:type rs:UserContext ;
rs:appliedOnItems ?itemClass ;
rs:appliedOnUsers ?userClass .
?item rdf:type ?itemClass .
OPTIONAL
{ ?userContext rs:hasWeightIfContextMatched ?weightMatched }
OPTIONAL
{ ?userContext rs:hasWeightIfContextDoesNotMatch ?weightNotMatched }
OPTIONAL
{ ?userContext rs:doNotRecommendInCaseNotMatch true
BIND(1 AS ?skip_)
}
bind(if (bound(?skip_) && (not EXISTS {?user a ?userClass}) , ?skip_, 0) as ?skip1)
values (?defaultUserMatched ?defaultUserNotMatched) {(1 0.5)}
BIND(if(EXISTS { ?user rdf:type ?userClass }, coalesce(?weightMatched, ?defaultUserMatched), coalesce(?weightNotMatched, ?defaultUserNotMatched)) AS ?weight)
}
values ?defaultNoUserContext {1}
BIND(if(bound(?skip1), ?skip1, 0) as ?skip)
BIND(if(bound(?weight), ?weight, ?defaultNoUserContext) AS ?userContextWeight)
}
this code is just a block in my real query, there is another block that brings the ?item
variable.
as you see, my code has ?item rdf:type ?itemClass
, but one of the bindings for ?item
is not from the type of ?itemClass
so the whole optional will not execute (for that binding), so when we go out of the optional, there is this line
BIND(if(bound(?weight), ?weight, ?defaultNoUserContext) AS ?userContextWeight)
the if
part will give false
so the ?userContextWeight
should be bound to ?defaultNoUserContext
. However, my code doesn't produce anything (any value at all) to these items . do you know why please?
again if you need data, i am more than welcome to give you, thanks
Now I see better, what i want is:
even if the item doesn't belong to the ?itemClass
, i need to give a default value for the ?userContextWeight
.
look at the update
OPTIONAL
{
VALUES ?user { rs:ania }
?userContext rdf:type rs:UserContext ;
rs:appliedOnItems ?itemClass ;
rs:appliedOnUsers ?userClass .
bind (if ( exists {?item rdf:type ?itemClass .}, true , false) as ?doesItemBelongToUserContextItemClass)
OPTIONAL
{ ?userContext rs:hasWeightIfContextMatched ?weightMatched }
OPTIONAL
{ ?userContext rs:hasWeightIfContextDoesNotMatch ?weightNotMatched }
OPTIONAL
{ ?userContext rs:doNotRecommendInCaseNotMatch true
BIND(1 AS ?skip_)
}
bind(if (bound(?skip_) && (not EXISTS {?user a ?userClass}) , ?skip_, 0) as ?skip1)
values (?defaultUserMatched ?defaultUserNotMatched) {(1 0.5)}
BIND(if(EXISTS { ?user rdf:type ?userClass }, coalesce(?weightMatched, ?defaultUserMatched), coalesce(?weightNotMatched, ?defaultUserNotMatched)) AS ?weight)
}
values ?defaultNoUserContext {1}
BIND(if(bound(?skip1), ?skip1, 0) as ?skip)
BIND( if ( !?doesItemBelongToUserContextItemClass , ?defaultNoUserContext ,if(bound(?weight), ?weight, ?defaultNoUserContext)) AS ?userContextWeight)
}
in the update, i check if the item belongs to the class or not using this bind
bind (if ( exists {?item rdf:type ?itemClass .}, true , false) as ?doesItemBelongToUserContextItemClass)
and then outside the optional
i do this
BIND( if ( !?doesItemBelongToUserContextItemClass , ?defaultNoUserContext ,if(bound(?weight), ?weight, ?defaultNoUserContext)) AS ?userContextWeight)
my problem is the value of ?userContextWeight
when the item doesn't belong to the class is ?weightNotMatched
, but it should be ?defaultNoUserContext
(look again at the last binding please)
any idea please?
by !?doesItemBelongToUserContextItemClass
I mean the normal boolean not that we study in algebra, maybe here it is not the same as there? this could be the problem?
I see that this
bind (if ( exists {?item a ?itemClass }, true , false) as ?doesItemBelongToUserContextItemClass)
always gives true
to doesItemBelongToUserContextItemClass
even though that is not correct, for a specific item
, it is not from the itemClass
.
now i am sure that the problem is here, because i printed the value of the doesItemBelongToUserContextItemClass
and it is always true but that is not correct, we are close, so just solving this will solve the question
Your query is big enough that I'm having a very hard time making sense of it, but my best guess is that you're running into a situation where your exists expression doesn't have all the variables bound that you need to make it test what you want it to test. Here's some very simple data:
@prefix : <urn:ex:>
:s a :D .
:t a :E .
Now, take a look at this query and the results:
prefix : <urn:ex:>
select * where {
#-- Find an individual ?a and (one of)
#-- the classes that it belongs to.
?a a ?aClass .
optional {
#-- Find an individual ?b and (one of)
#-- the classes that it belongs to.
?b a ?bClass .
#-- And bind ?isCommonClass to true or
#-- false, to indicate whether ?b is
#-- also an element of ?aClass.
bind(exists{?b a ?aClass} as ?isCommonClass)
}
}
---------------------------------------------
| a | aClass | b | bClass | isCommonClass |
=============================================
| :s | :D | :s | :D | true |
| :s | :D | :t | :E | true |
| :t | :E | :s | :D | true |
| :t | :E | :t | :E | true |
---------------------------------------------
?isCommonClass is always true, even though it seems like it should be true when ?a and ?b are the same, and false otherwise. I think that what's happening here is that the bind gets evaluated in a context where either ?b or ?aClass isn't set yet, so the exists is actually checking for something more general. We can test this by moving the bind outside of the optional:
select * where {
?a a ?aClass .
optional {
?b a ?bClass .
}
bind(exists{?b a ?aClass} as ?isCommonClass)
}
---------------------------------------------
| a | aClass | b | bClass | isCommonClass |
=============================================
| :s | :D | :s | :D | true |
| :s | :D | :t | :E | false |
| :t | :E | :s | :D | false |
| :t | :E | :t | :E | true |
---------------------------------------------
Here, we get the results we'd expect, with ?isCommonClass being true exactly when ?a and ?b are the same.
The query snippet in the question doesn't provide enough to be sure that this is what's happening, and the query you provided in the comments is too big for anyone else to check, but this seems like a very good candidate for what's going on in your situation.