Hi Andy!

On 11/12/15 13:54, Andy Seaborne wrote:
On 10/12/15 20:18, Osma Suominen wrote:
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX text: <http://jena.apache.org/text#>

SELECT *
WHERE {
   GRAPH <http://www.yso.fi/onto/yso/> {
     GRAPH <urn:x-arq:UnionGraph>  {
       (?s ?score ?literal) text:query 'musiikkikasv*' .
     }
     ?s skos:prefLabel ?label .
     FILTER (LANG(?label)=LANG(?literal))
   }
}

You are running with union default graph? In which case that's good.

Yes, I'm using unionDefaultGraph=true.

Else use <urn:x-arq:DefaultGraph>

Right.

One of my regrets in SPARQL is that you can't get back to the default
graph inside a GRAPH block.

Exactly. That's the problem here, and the workaround requires using these magic ARQ graph names. Or...

The key to your query is the back that the FILTER covers the inner GRAPH.

This should work:

WHERE {
    (?s ?score ?literal) text:query 'musiikkikasv*' .
    GRAPH <http://www.yso.fi/onto/yso/> { ?s skos:prefLabel ?label . }
    FILTER (LANG(?label)=LANG(?literal))
}

and it gets optimized into a

...something missing from your sentence?

Indeed, this works. It's also faster than I expected (20ms). It appears that when the expression within the GRAPH block gets executed, ?s is already bound to a single resource (as returned by text:query). Otherwise the { ?s skos:prefLabel ?label } pattern would have to iterate over many potential solutions, which would have taken more time.

You had an OPTIONAL in the original:

WHERE {
     (?s ?score ?literal) text:query 'musiikkikasv*' .
     OPTIONAL {
         GRAPH <http://www.yso.fi/onto/yso/>
         { ?s skos:prefLabel ?label . }
     }
     FILTER (!BOUND(?label) || LANG(?label)=LANG(?literal))
}

or

WHERE {
(?s ?score ?literal) text:query 'musiikkikasv*' .
    OPTIONAL {
      GRAPH <http://www.yso.fi/onto/yso/>
       { ?s skos:prefLabel ?label . }
      FILTER (LANG(?label)=LANG(?literal))
    }
}

In this one it is very important the FILTER is at the top level of the
OPTIONAL{} block.  It puts ?literal in-scope because the FILTER is part
of the LeftJoin condition.

I see - moving the FILTER is indeed the key. I don't quite understand all the magic that's happening here, but I think I can use this to get a working solution.

Thanks a lot for all the explanations and help!

-Osma


--
Osma Suominen
D.Sc. (Tech), Information Systems Specialist
National Library of Finland
P.O. Box 26 (Kaikukatu 4)
00014 HELSINGIN YLIOPISTO
Tel. +358 50 3199529
[email protected]
http://www.nationallibrary.fi

Reply via email to