4

Let's say I make the following insertions into my GraphDB 8.3 triplestore:

PREFIX : <http://example.com/>
insert data { :hello a :word }

and

PREFIX : <http://example.com/>
insert data { graph :farewells { :goodbye a :word }}

now, if I ask

select * where {
    graph ?g {
        ?s ?p ?o .
    } 
}

I only get

+--------------------------------+------------------------------+---------------------------------------------------+---------------------------+
|               ?g               |              ?s              |                        ?p                         |            ?o             |
+--------------------------------+------------------------------+---------------------------------------------------+---------------------------+
| <http://example.com/farewells> | <http://example.com/goodbye> | <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> | <http://example.com/word> |
+--------------------------------+------------------------------+---------------------------------------------------+---------------------------+

I can obviously get both "triples about words" with the following, but then the named-graph membership is not shown

select * { ?s ?p ?o }

How can I write a query that retrieves both triples about words and indicates that { :goodbye a :word } comes from graph :farewells ?

Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
Mark Miller
  • 3,011
  • 1
  • 14
  • 34

3 Answers3

7

You can do something along these lines:

SELECT * 
WHERE {
   { GRAPH ?g { ?s ?p ?o } }
   UNION
   { ?s ?p ?o .
     FILTER NOT EXISTS { GRAPH ?g { ?s ?p ?o } } 
   }
}

The first part of the union selects all triples in named graphs. The second part grabs all triples in the default graph, explicitly excluding patterns that occur in a named graph.

Jeen Broekstra
  • 21,642
  • 4
  • 51
  • 73
5

In GraphDB, you could use pseudographs for this purpose, i. e. <http://www.ontotext.com/explicit> (it seems you are not using inferencing).

Try this query:

SELECT * FROM NAMED <http://www.ontotext.com/explicit>
{ GRAPH ?g { ?s ?p ?o } }

The result should be:

+------------------------------------+----------+-----------+-------+
| ?g                                 | ?s       | ?p        | ?o    |
+------------------------------------+----------+-----------+-------+
| <http://www.ontotext.com/explicit> | :hello   | rdf:type  | :word |
| :farewells                         | :goodbye | rdf:type  | :word |
+------------------------------------+----------+-----------+-------+

For comparison, note that

SELECT * FROM NAMED <http://www.openrdf.org/schema/sesame#nil>
{ GRAPH ?g { ?s ?p ?o } }

will return only

+------------------------------------+----------+-----------+-------+
| ?g                                 | ?s       | ?p        | ?o    |
+------------------------------------+----------+-----------+-------+
| <http://www.ontotext.com/explicit> | :hello   | rdf:type  | :word |
+------------------------------------+----------+-----------+-------+
Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
1

Short "answer": avoid putting data into the default graph in GraphDB (and other triple stores with a "virtual" default graph which is just a UNION of all named graphs)

Background: GraphDB decided to define the default graph as the union of all named graphs and the default graph. This behaviour is not backed by the SPARQL semantics specification, but is implementation-specific behaviour.

So you really have three options:

  1. Use FILTER NOT EXISTS or MINUS as explained by Jeen Broekstra. This can have a serious negative impact on query performance.

  2. Use the GraphDB pseudographs as exemplified by Stanislav Kralin. This option makes your queries (and your system) dependent on GraphDB -- you can not change the SPARQL engine later, without adapting your queries.

  3. Avoid putting data into the default graph. You might define "your own" default graph, e.g. call it http://default/, and put it in the SPARQL FROM clause.

Other triple stores allow to enable/disable this feature. I couldn't find a switch in the documentation of GraphDB. Otherwise this would be the 4th, and my preferred, option.

  • 1
    This behaviour is allowed: https://www.w3.org/TR/2013/REC-sparql11-service-description-20130321/#sd-uniondefaultgraph – Stanislav Kralin Oct 14 '17 at 10:35
  • @StanislavKralin yes, it is allowed as part of the service description. But the semantics of SPARQL is not defined in this way. While I understand the purpose of this feature, it might confuse SPARQL users. I clarified the answer accordingly. – Stefan Bischof Oct 18 '17 at 09:43
  • Just a minor (late) correction: the GraphDB behavior _is_ backed by the SPARQL specification, which does not favor one interpretation of what the default graph contains over another. – Jeen Broekstra Oct 28 '22 at 22:26