15

I am attempting to use a SPARQL Construct query to create a new named graph from an existing one. The database I am querying contains http://graph.com/old as an existing named graph. I am using Jena TDB as the database, accessed through a Jena Fuseki endpoint. The below query gives me an error:

CONSTRUCT
{
    GRAPH <http://graph.com/new> {
        ?s ?p ?o
    }
}

WHERE
{
    GRAPH <http://graph.com/old> {
        ?s ?p ?o
    }
}

If I remove the graph statement from the CONSTRUCT block, the query works perfectly, but I would like to place the triples into a named graph that I specify instead of the default one.

As far as I could find, the SPARQL 1.1 section on CONSTRUCT does not say anything about constructing into named graphs. Is there a way to do this?

Stanislav Kralin
  • 10,115
  • 4
  • 30
  • 52
Yoav Zimmerman
  • 468
  • 4
  • 10

1 Answers1

19

Just as SELECT queries are used when you are interested in getting a set of variable bindings back, CONSTRUCT queries are used you are interested in getting a model back. Just as the variables bound in a SELECT result set are not put into any model or persistent set of bindings, neither is the model built by a CONSTRUCT stored anywhere. You want to use SPARQL 1.1 INSERT. The update features are described in 3 SPARQL 1.1 Update Language. Your update request can thus be written as:

INSERT {
  GRAPH <http://graph.com/new> {
    ?s ?p ?o
  }
}
WHERE {
  GRAPH <http://graph.com/old> {
    ?s ?p ?o
  }
}

For this particular case, though, you might be able to use the COPY operation described in 3.2.3 COPY. COPY removes all the data from the target graph first though, so it might not be applicable to your actual case (understanding that the code you provided may be a minimal example, and not necessarily the actual update you're trying to perform). About COPY the standard says:

The COPY operation is a shortcut for inserting all data from an input graph into a destination graph. Data from the input graph is not affected, but data from the destination graph, if any, is removed before insertion.

COPY ( SILENT )? ( ( GRAPH )? IRIref_from | DEFAULT) TO ( ( GRAPH )? IRIref_to | DEFAULT )

is similar in operation to:

DROP SILENT (GRAPH IRIref_to | DEFAULT);
      INSERT { ( GRAPH IRIref_to )? { ?s ?p ?o } } WHERE { ( GRAPH IRIref_from )? { ?s ?p ?o } }

The difference between COPY and the DROP/INSERT combination is that if COPY is used to copy a graph onto itself then no operation will be performed and the data will be left as it was. Using DROP/INSERT in this situation would result in an empty graph.

If the destination graph does not exist, it will be created. By default, the service may return failure if the input graph does not exist. If SILENT is present, the result of the operation will always be success.

If COPY isn't suitable, then ADD may be what you're looking for:

3.2.5 ADD

The ADD operation is a shortcut for inserting all data from an input graph into a destination graph. Data from the input graph is not affected, and initial data from the destination graph, if any, is kept intact.

ADD ( SILENT )? ( ( GRAPH )? IRIref_from | DEFAULT) TO ( ( GRAPH )? IRIref_to | DEFAULT)

is equivalent to:

INSERT { ( GRAPH IRIref_to )? { ?s ?p ?o } } WHERE { ( GRAPH IRIref_from )? { ?s ?p ?o } }

If the destination graph does not exist, it will be created. By default, the service may return failure if the input graph does not exist. If SILENT is present, the result of the operation will always be success.

Joshua Taylor
  • 80,876
  • 9
  • 135
  • 306
  • 2
    The alternative to `COPY` is of course `ADD`, this copies the data from the source to the target and preserves the target graphs existing data – RobV Aug 21 '13 at 18:11
  • @RobV Good point! I haven't done much SPARQL 1.1 Updating, and I guess I didn't read far enough into the spec after finding COPY. I'll add ADD. – Joshua Taylor Aug 21 '13 at 18:25