문제

Given a generic graph of objects and directed relations:

@prefix obj: <http://example.org/obj/> .
@prefix rel: <http://example.org/rel/> .

obj:obj1 rel:rel1 obj:obj2 .
obj:obj3 rel:rel2 obj:obj2 .
obj:obj9 rel:rel5 obj:obj8 .
obj:obj1 rel:rel1 obj:obj3 .

and a subset of objects, say obj1, obj2, obj3, how do I extract the subgraph that contains only this subset of objects regardless of the specific relations from the full graph using a simple SPARQL query? The resulting subgraph should be:

obj:obj1 rel:rel1 obj:obj2 .
obj:obj3 rel:rel2 obj:obj2 .
obj:obj1 rel:rel1 obj:obj3 .

my current attempt is to try every possible relations using a bunch of OPTIONAL clauses, which probably isn't the best way to go about it:

SELECT ?r1 ?r2 ?r3 ?r4 ?r5 ?r6 WHERE {
OPTIONAL {obj:obj1 ?r1 obj:obj2} .
OPTIONAL {obj:obj1 ?r2 obj:obj3} .
OPTIONAL {obj:obj2 ?r3 obj:obj3} .
OPTIONAL {obj:obj2 ?r4 obj:obj1} .
OPTIONAL {obj:obj3 ?r5 obj:obj1} .
OPTIONAL {obj:obj3 ?r6 obj:obj2} . }
도움이 되었습니까?

해결책

Given this data (which is essentially yours, except that I've added the .s at the end of the lines so that it's valid Turtle, and I've added a couple of triples so that we'll be able to see whether just having a subject or object not in the special set will keep the triple out of the results):

@prefix obj: <http://example.org/obj/> .
@prefix rel: <http://example.org/rel/> .

obj:obj1 rel:rel1 obj:obj2 .
obj:obj3 rel:rel2 obj:obj2 .
obj:obj1 rel:rel4 obj:obj8 . # additional triple
obj:obj9 rel:rel7 obj:obj2 . # additional triple
obj:obj9 rel:rel5 obj:obj8 .
obj:obj1 rel:rel1 obj:obj3 .

You could use a query like this:

prefix obj: <http://example.org/obj/>

select ?s ?p ?o where { 
  values ?s { obj:obj1 obj:obj2 obj:obj3 }
  values ?o { obj:obj1 obj:obj2 obj:obj3 }
  ?s ?p ?o .
}

to get results like this:

$ sparql --query query.rq --data data.n3
----------------------------------
| s        | p        | o        |
==================================
| obj:obj1 | rel:rel1 | obj:obj3 |
| obj:obj1 | rel:rel1 | obj:obj2 |
| obj:obj3 | rel:rel2 | obj:obj2 |
----------------------------------

The use of values here just says that ?s has to be drawn from a particular set of values, and that ?o has to be drawn from a particular set of values. I don't think there's a way to avoid having to repeat the list of special resources in each location. That is, you'll have to write { obj:obj1 obj:obj2 obj:obj3 } twice, but that's still much easier than enumerating all the possible combinations.

You might also consider using a construct here, rather than select, if what you want back is actually the graph, rather than a set of variable bindings. E.g., with this query:

prefix obj: <http://example.org/obj/>

construct { ?s ?p ?o } where { 
  values ?s { obj:obj1 obj:obj2 obj:obj3 }
  values ?o { obj:obj1 obj:obj2 obj:obj3 }
  ?s ?p ?o .
}

you can get the actual RDF graph back:

$ sparql -out TTL --query query.rq --data data.n3
@prefix obj:   <http://example.org/obj/> .
@prefix rel:   <http://example.org/rel/> .

obj:obj1  rel:rel1  obj:obj3 , obj:obj2 .

obj:obj3  rel:rel2  obj:obj2 .
$ sparql -out N-Triples --query query.rq --data data.n3
<http://example.org/obj/obj1> <http://example.org/rel/rel1> <http://example.org/obj/obj3> .
<http://example.org/obj/obj1> <http://example.org/rel/rel1> <http://example.org/obj/obj2> .
<http://example.org/obj/obj3> <http://example.org/rel/rel2> <http://example.org/obj/obj2> .
$ sparql -out RDF/XML --query query.rq --data data.n3
<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:obj="http://example.org/obj/"
    xmlns:rel="http://example.org/rel/">
  <rdf:Description rdf:about="http://example.org/obj/obj1">
    <rel:rel1>
      <rdf:Description rdf:about="http://example.org/obj/obj3">
        <rel:rel2 rdf:resource="http://example.org/obj/obj2"/>
      </rdf:Description>
    </rel:rel1>
    <rel:rel1 rdf:resource="http://example.org/obj/obj2"/>
  </rdf:Description>
</rdf:RDF>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top