How to return all S->P->O triples from a starting

2019-04-13 06:22发布

问题:

My goal is to graphically represent the S->P->O relations within a depth two edges from the specified resource, p:Person_1. I want all relations within that path length to be returned from my query as ?s, ?p, ?o for further processing in my graphical application.

I tried the first query below which gives me my first set of ?s ?p ?o with repeats, then ?p2, ?o2, ?p3, ?o3 as additional columns in the result. I want to bind ?p2 and ?p3 to ?p, ?o2 and ?o3 to ?o.

  SELECT *
    WHERE {
        p:Person_1 ?p ?o .
        BIND("p:Person_1" as ?s)
        OPTIONAL{
            ?o ?p2 ?o2 .
        }
        OPTIONAL{
            ?o2 ?p3 ?o3 .
        }
    }

Then, based on How do I construct get the whole sub graph from a given resource in RDF Graph?, I tried using CONSTRUCT to return the graph.

PREFIX p: <http://www.example.org/person/> 
PREFIX x: <example.org/foo/>

construct { ?s ?p ?o }
FROM <http://localhost:8890/MYGRAPH>
where { p:Person_1 (x:|!x:)* ?s . 
        ?s ?p ?o . 
}

I am using Virtuoso and I get the error:

Virtuoso 37000 Error SP031: SPARQL compiler: Variable ?_::trans_subj_9_3 in T_IN list is not a value from some triple

I could post-process the result from my first query but I want to learn how to do this correctly with SPARQL, preferably on Virtuoso.

Update after testing the advice from @AKSW : Both CONSTRUCT and SELECT statements work with the pattern suggested.

CONSTRUCT { ?s ?p ?o }
FROM <http://localhost:8890/MYGRAPH>
where { p:Person_1 (x:foo|!x:bar)* ?s . 
        ?s ?p ?o . 
} LIMIT 100

and:

SELECT s ?p ?o 
FROM <http://localhost:8890/MYGRAPH>
where { p:Person_1 (x:foo|!x:bar)* ?s . 
        ?s ?p ?o . 
} LIMIT 100

The SELECT results in several duplicates that cannot be removed using DISTINCT, which results in an error that I assume is due to the 'datatype' of some of the returned values.

Virtuoso 22023 Error SR066: Unsupported case in CONVERT (DATETIME -> IRI_ID)

It appears some post-SPARQL processing is in order.

This gets me most of the way there. Still hoping I can find a solution for SPARQL that is like Cypher's "number of hops away" :

OPTIONAL MATCH path=s-[*1..3]-(o)

回答1:

Here is a SPARQL query that works in Virtuoso. Note the SPARQL W3C standard does not support this syntax and it will fail in other triplestores.

PREFIX p: <http://www.example.org/person/> 
PREFIX x: <example.org/foo/>
# CONSTRUCT {?s ?p ?o}  # If you wish to return the graph
SELECT ?s ?p ?o   # To return the triples
FROM <http://localhost:8890/MYGRAPH>
where { p:Person_1 (x:foo|!x:bar){1,3} ?s  .
  ?s ?p ?o .
}LIMIT 100

See also K. Idehen's wiki entry here: http://linkedwiki.com/exampleView.php?ex_id=141

And thanks to @Joshua Taylor for advice in the same area.



回答2:

Working Drafts of SPARQL 1.1 Property Paths included the {n,m} operator for handling this issue, which was implemented (and will remain supported) in Virtuoso. Here's a tweak to @tim's response.

  • Live SPARQL Query Results Page using the DBpedia endpoint (which is a Virtuoso instance).

  • Live SPARQL Query Definition Page that opens up query source code in the default DBpedia query editor.

  • Actual Query Example:

    PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
    SELECT DISTINCT ?s AS ?Entity 
                    ?o AS ?Category 
    WHERE { 
            ?s  rdf:type       <http://dbpedia.org/ontology/AcademicJournal> ; 
                rdf:type{1,3}  ?o 
          } 
    LIMIT 100
    


回答3:

Should you be looking for LinkedIn-like presentation of Contact Networks and Degrees of Separation between individuals, here is an example using Virtuoso-specific SPARQL Extensions that solve this particular issue:

SELECT ?o                                              AS ?WebID
       ((SELECT COUNT (*) WHERE {?o foaf:knows ?xx}))  AS ?contact_network_size
       ?dist                                           AS ?DegreeOfSeparation 
       <http://www.w3.org/People/Berners-Lee/card#i>   AS ?knowee
  WHERE
    {
      {
        SELECT ?s ?o
        WHERE
          {
            ?s foaf:knows ?o
          }
      } OPTION (TRANSITIVE, t_distinct, t_in(?s), t_out(?o), t_min (1), t_max (4), t_step ('step_no') AS ?dist) .
      FILTER (?s= <http://www.w3.org/People/Berners-Lee/card#i>)
      FILTER (isIRI(?s) and isIRI(?o))
    }
  ORDER BY ?dist DESC (?contact_network_size)
  LIMIT 500

Note: this approach is the only way (at the current time) to expose actual relational hops between entities in an Entity Relationship Graph that includes Transitive relations.

  • Live Link to Query Results
  • Live Link to Query Source Code


回答4:

Bearing in mind that the r{n,m} operator was deprecated in the final SPARQL 1.1 (but will remain supported in Virtuoso), you can use r/r?/r? instead of r{1,3}, if you want to work strictly off the current spec:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
SELECT DISTINCT ?s AS ?Entity 
                ?o AS ?Category 
WHERE { 
        ?s  rdf:type                          <http://dbpedia.org/ontology/AcademicJournal> ; 
            rdf:type / rdf:type? / rdf:type?  ?o 
       }
LIMIT 100

Here's a live example, against the DBpedia instance hosted in Virtuoso.