In a prior blog (SPARQL: Updating the URI of an owl:Class in place) we looked into how to use SPARQL to rename a class in a triple store. The main steps are below. We showed how to do this for the example of renaming the class veh:Auto
to veh:Car
.
- change the instances of the old class to be instances of the new class
- replace the triples where the class is used in either the subject or object of the triple
- look around for anywhere else the old class name is used, and change accordingly.
The last step addresses the fact that there are a few other things that you might need to do to address all the consequences of renaming a class. Today we will see how to handle the situation where your instances use a naming convention that includes the name of the class. Let’s say the instances of Car (formerly Auto) are all like this: veh:_Auto_234
and veh:_Auto_12
. We will want to change them to be like: veh:_Car_234
.
The main steps are:
- Figure out how you are going to use SPARQL string operations to create the new URI given an old URI.
- Replace triples using the oldURI in the object of a triple.
- Determine where the oldURI is used as the object in a triple, and use
CONSTRUCT
to preview the new triples using the results of step 1. - Use
DELETE
andINSERT
to swap out the old triples with the new URI in the object.
- Determine where the oldURI is used as the object in a triple, and use
- Replace triples using the oldURI in the subject of a triple.
- Determine where the oldURI is used as the subject in a triple, and use
CONSTRUCT
to preview the new triples using the results of step 1. - Use
DELETE
andINSERT
to swap out the old triples with the new URI in the subject
- Determine where the oldURI is used as the subject in a triple, and use
In practice, we do step 1 and step 2a at the same time. We find a specific instance, and filter on just that one (e.g. veh:_Auto_234
) to keep things simple. Because we will be using strings to create URIs, we have to spell the namespaces out in full, or else the URI will incorrectly contain the string “veh:” instead the expanded form, which is: “http://ontologies.myorg.com/vehicles#”.
CONSTRUCT {?s ?p ?newURI} WHERE {?oldURI rdf:type veh:Car . ?s ?p ?oldURI. FILTER (?oldURI in (veh:_Auto_234)) BIND (URI(CONCAT ("http://ontologies.myorg.com/vehicles#_Car_", STRAFTER (STR(?oldURI),"_Auto_"))) AS ?newURI) }
This should return a table something like this:
Subject | Predicate | Object |
veh:_TomJones | gist:owns | veh:_Car_234 |
veh:_JaneWrenchTurner | veh:repaired | veh:_Car_234 |
veh:_PeterSeller | veh:sold | veh:_Car_234 |
This tells you there are exactly three triples with veh:_Auto_234
in the object, and shows you what the new triples will be when you replace the old ones. After this, you might want to remove the FILTER
and see a wider range of triples, setting a LIMIT as needed. Now you are ready to do the actual replacement (step 2b). This is what you do:
- Add a
DELETE
statement to remove the triple that will be replaced. - Replace the “
CONSTRUCT
” with “INSERT
” leaving alone what is in the brackets. - Leave the
WHERE
clause as it is, except to remove theFILTER
statement, if it is still there (or just comment it out).
Sample Graph of Triples
This will do the change in place for all affected triples. Note that we have constructed the URI from scratch, when all we really needed to do was do a string replace. The latter is simpler and more robust. Using CONCAT
and STRAFTER
gives the wrong answer if the string “_Auto_
” does not appear in the URI. Here is the query to execute, with the simpler string operation:
DELETE {?s ?p ?oldURI} INSERT {?s ?p ?newURI } WHERE {?oldURI rdf:type veh:Car . ?s ?p ?oldURI . BIND (URI(REPLACE(STR(?oldURI), "_Auto_", "_Car_")) AS ?newURI) }
Step 3 is pretty much identical, except flip the subject and object. In fact, you can combine steps 2 and 3 into a single query. There are a few things to watch out for:
- VERY IMPORTANT: make sure you do steps 2 and 3 in order. If you do step 3 first, you will blow away the rdf:type statements that are needed to do step 2.
- It is easy to make mistakes, backup the store and work on a copy.
- When creating URIs from strings, use full namespaces rather than the abbreviated qname format.
- Check the count of all the triples before and after each time you make a change, track down any differences.