Skip to content

GRAPH — query named graphs ​

Every triple in pgRDF lives in a graph (see Managing graphs). A pattern without GRAPH matches across all of them, including the default graph. GRAPH narrows it down.

FormMatches
GRAPH <iri> { … }Only the graph with that IRI. An IRI that names no graph matches nothing.
GRAPH ?g { … }Each named graph in turn, with ?g bound to its IRI. The default graph is not included.
No GRAPHAll graphs, including the default graph.

The default graph's IRI is urn:pgrdf:graph:0, so GRAPH <urn:pgrdf:graph:0> { … } reads only the default graph.

FROM and FROM NAMED are ignored

FROM <iri> and FROM NAMED <iri> are accepted but currently have no effect: the query still runs over all graphs. Use GRAPH to choose graphs.

Example data ​

Two small graphs, next to the people graph from the sample data:

sql
SELECT pgrdf.add_graph('http://example.org/g1');
SELECT pgrdf.add_graph('http://example.org/g2');
SELECT pgrdf.parse_turtle('@prefix ex: <http://example.org/> . ex:a ex:p "in g1" .',
                          pgrdf.graph_id('http://example.org/g1'));
SELECT pgrdf.parse_turtle('@prefix ex: <http://example.org/> . ex:a ex:p "in g2" . ex:b ex:p "only g2" .',
                          pgrdf.graph_id('http://example.org/g2'));

Remove them afterwards with SELECT pgrdf.drop_graph('http://example.org/g1'); and the same for g2.

One graph ​

sql
SELECT * FROM pgrdf.sparql($$
  SELECT ?s ?o
  WHERE { GRAPH <http://example.org/g1> { ?s ?p ?o } }
$$);
--  {"o": "in g1", "s": "http://example.org/a"}

Which graphs match ​

GRAPH ?g tells you where each answer came from:

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX ex: <http://example.org/>
  SELECT ?g ?o WHERE { GRAPH ?g { ex:a ex:p ?o } }
  ORDER BY ?g
$$);
--  {"g": "http://example.org/g1", "o": "in g1"}
--  {"g": "http://example.org/g2", "o": "in g2"}

Combined with an aggregate, it counts triples per graph:

sql
SELECT * FROM pgrdf.sparql($$
  SELECT ?g (COUNT(*) AS ?n)
  WHERE { GRAPH ?g { ?s ?p ?o } }
  GROUP BY ?g ORDER BY ?g
$$);
--  {"g": "http://example.org/g1", "n": "1"}
--  {"g": "http://example.org/g2", "n": "2"}
--  {"g": "http://example.org/people", "n": "14"}

Combining with OPTIONAL, UNION and MINUS ​

OPTIONAL inside GRAPH ​

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  SELECT ?g ?name ?mbox
  WHERE { GRAPH ?g { ?s foaf:name ?name
                     OPTIONAL { ?s foaf:mbox ?mbox } } }
  ORDER BY ?name
$$);
--  {"g": "http://example.org/people", "mbox": "mailto:alice@example.org", "name": "Alice"}
--  {"g": "http://example.org/people", "mbox": null, "name": "Bob"}
--  {"g": "http://example.org/people", "mbox": "mailto:carol@example.org", "name": "Carol"}

UNION across two graphs ​

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX ex: <http://example.org/>
  SELECT ?s ?o
  WHERE { { GRAPH <http://example.org/g1> { ?s ex:p ?o } }
          UNION
          { GRAPH <http://example.org/g2> { ?s ex:p ?o } } }
  ORDER BY ?o
$$);
--  {"o": "in g1", "s": "http://example.org/a"}
--  {"o": "in g2", "s": "http://example.org/a"}
--  {"o": "only g2", "s": "http://example.org/b"}

MINUS to subtract one graph from another ​

Subjects in g2 that g1 doesn't mention, the way you'd compare a graph with an earlier snapshot:

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX ex: <http://example.org/>
  SELECT ?s
  WHERE { GRAPH <http://example.org/g2> { ?s ex:p ?o }
          MINUS { GRAPH <http://example.org/g1> { ?s ex:p ?o2 } } }
$$);
--  {"s": "http://example.org/b"}

Choosing graphs by list ​

VALUES ?g { … } and FILTER(?g = …) on the variable of GRAPH ?g are refused with an error. Either name each graph in a UNION (as in UNION across two graphs), or query all graphs with GRAPH ?g and keep the ones you want in SQL:

sql
SELECT sparql
  FROM pgrdf.sparql($$
    PREFIX ex: <http://example.org/>
    SELECT ?g ?o WHERE { GRAPH ?g { ex:a ex:p ?o } }
  $$)
 WHERE sparql->>'g' IN ('http://example.org/g1', 'http://example.org/g2')
 ORDER BY 1;
--  {"g": "http://example.org/g1", "o": "in g1"}
--  {"g": "http://example.org/g2", "o": "in g2"}

In updates ​

GRAPH <iri> { … } works in the templates and patterns of SPARQL UPDATE too, and WITH <iri> scopes a whole update to one graph. Check which graph an update writes to before running one.

See also ​

pgRDF is released under the MIT license. Documentation built with VitePress, served via GitHub Pages.