Re: Conditional INSERT statements
Hi Andy, Just to complete the thread and for anyone else that needs to do something similar, we now have this working nicely using two operations, as you suggested. Here is the code... DELETE { ?transfer dri:transferAsset ?transferAsset . ?transferAsset ?transferAssetProperty ?transferAssetValue . } WHERE { ?transfer dcterms:identifier 20130628134601^^xsd:string . ?subject dcterms:identifier 9a10d7cf-c7e8-4e06-91c7-1d46aaa6e52e^^xsd:string . OPTIONAL { ?transfer dri:transferAsset ?transferAsset . ?transferAsset dcterms:subject ?subject ; dcterms:modified ?transferAssetModified ; ?transferAssetProperty ?transferAssetValue . FILTER(?transferAssetModified 2013-06-28T15:21:00Z^^xsd:dateTime) } }; INSERT { ?transfer dri:transferAsset [ dri:transferAssetStatus http://nationalarchives.gov.uk/dri/catalogue/transferAssetStatus#COMPLETED ; dcterms:modified 2013-06-28T15:21:00Z^^xsd:dateTime ; dcterms:subject ?subject ] } WHERE { # where the transfer asset doesn't exist - i.e it is new or has not been deleted ?transfer dcterms:identifier 20130628134601^^xsd:string . ?subject dcterms:identifier 9a10d7cf-c7e8-4e06-91c7-1d46aaa6e52e^^xsd:string . FILTER(NOT EXISTS { ?transfer dri:transferAsset [ dcterms:subject ?subject ] . }) } So basically the delete is conditional, as before, but now the insert is conditional on the delete having occurred. Easy when you know how :-) Thanks for your help! Rob On Sat, Jun 15, 2013 at 2:02 PM, Andy Seaborne a...@apache.org wrote: PREFIX dri: http://nationalarchives.gov.**uk/terms/dri#http://nationalarchives.gov.uk/terms/dri# PREFIX rdfs: http://www.w3.org/2000/01/**rdf-schema#http://www.w3.org/2000/01/rdf-schema# PREFIX status: http://nationalarchives.gov.**uk/dri/catalogue/** transferAssetStatus#http://nationalarchives.gov.uk/dri/catalogue/transferAssetStatus# PREFIX dct: http://purl.org/dc/terms/ PREFIX xsd: http://www.w3.org/2001/**XMLSchema#http://www.w3.org/2001/XMLSchema# PREFIX rdf: http://www.w3.org/1999/02/22-**rdf-syntax-ns#http://www.w3.org/1999/02/22-rdf-syntax-ns# DELETE { ?transfer dri:transferAsset ?transferAsset . } INSERT { ?transfer dri:transferAsset _:b0 . _:b0 dct:subject ?subject . _:b0 dri:transferAssetStatus status:SENT . _:b0 dct:modified 2013-06-13T11:58:23.468Z^^**xsd:dateTime . } WHERE { ?transfer dct:identifier 201305241200^^xsd:string . ?subject dct:identifier dff82497-f161-4afd-8e38-** f31a8b475b43^^xsd:string OPTIONAL { ?transfer dri:transferAsset ?transferAsset . ?transferAsset dct:subject ?subject . ?transferAsset dct:modified ?transferAssetModified FILTER ( ?transferAssetModified 2013-06-13T11:58:23.468Z^^**xsd:dateTime ) } } Rob, (which version of the software?) The example data does not look like the DELETE was applied - there is still a dri:transferAsset link to the old state. I would have expected the bnode still to be there but the triple connecting it should have gone. If so, then the OPTIONAL is not matching -- it sets ?transferAsset. In your example, the ?subject dct:identifier ... does not match either but an INSERT does seem to have happened. Could you delete all ?transferAsset completely? The new state only depends on the new status if it's a legal state transition for the status. To cope with the fact that COMPLETED can come before SENDING, test the status. DELETE { ?transfer dri:transferAsset ?transferAsset . ?transferAsset ?p ?o . } INSERT { ?transfer dri:transferAsset _:b0 . _:b0 dct:subject ?subject . _:b0 dri:transferAssetStatus status:SENT . _:b0 dct:modified 2013-06-13T11:58:23.468Z^^**xsd:dateTime . } WHERE { ?transfer dct:identifier 201305241200^^xsd:string ; dri:transferAssetStatus ?status ; dri:transferAsset ?transferAsset . FILTER (?status != status:COMPLETED) ?transferAsset ?p ?o . } ; SPARQL Updates can be several operations in one request. It may be easier to have two operations DELETE { ... } WHERE { ... } ; INSERT { ... } WHERE { ... } Andy -- Rob Walpole Email robkwalp...@gmail.com Tel. +44 (0)7969 869881 Skype: RobertWalpolehttp://www.linkedin.com/in/robwalpole
Re: Conditional INSERT statements
PREFIX dri: http://nationalarchives.gov.uk/terms/dri# PREFIX rdfs: http://www.w3.org/2000/01/rdf-schema# PREFIX status: http://nationalarchives.gov.uk/dri/catalogue/transferAssetStatus# PREFIX dct: http://purl.org/dc/terms/ PREFIX xsd: http://www.w3.org/2001/XMLSchema# PREFIX rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# DELETE { ?transfer dri:transferAsset ?transferAsset . } INSERT { ?transfer dri:transferAsset _:b0 . _:b0 dct:subject ?subject . _:b0 dri:transferAssetStatus status:SENT . _:b0 dct:modified 2013-06-13T11:58:23.468Z^^xsd:dateTime . } WHERE { ?transfer dct:identifier 201305241200^^xsd:string . ?subject dct:identifier dff82497-f161-4afd-8e38-f31a8b475b43^^xsd:string OPTIONAL { ?transfer dri:transferAsset ?transferAsset . ?transferAsset dct:subject ?subject . ?transferAsset dct:modified ?transferAssetModified FILTER ( ?transferAssetModified 2013-06-13T11:58:23.468Z^^xsd:dateTime ) } } Rob, (which version of the software?) The example data does not look like the DELETE was applied - there is still a dri:transferAsset link to the old state. I would have expected the bnode still to be there but the triple connecting it should have gone. If so, then the OPTIONAL is not matching -- it sets ?transferAsset. In your example, the ?subject dct:identifier ... does not match either but an INSERT does seem to have happened. Could you delete all ?transferAsset completely? The new state only depends on the new status if it's a legal state transition for the status. To cope with the fact that COMPLETED can come before SENDING, test the status. DELETE { ?transfer dri:transferAsset ?transferAsset . ?transferAsset ?p ?o . } INSERT { ?transfer dri:transferAsset _:b0 . _:b0 dct:subject ?subject . _:b0 dri:transferAssetStatus status:SENT . _:b0 dct:modified 2013-06-13T11:58:23.468Z^^xsd:dateTime . } WHERE { ?transfer dct:identifier 201305241200^^xsd:string ; dri:transferAssetStatus ?status ; dri:transferAsset ?transferAsset . FILTER (?status != status:COMPLETED) ?transferAsset ?p ?o . } ; SPARQL Updates can be several operations in one request. It may be easier to have two operations DELETE { ... } WHERE { ... } ; INSERT { ... } WHERE { ... } Andy
Re: Conditional INSERT statements
Hi Andy, Thanks for your reply... On Thu, Jun 13, 2013 at 11:26 PM, Andy Seaborne a...@apache.org wrote: Immediate comments: 1/ DELETE { ?transfer http://nationalarchives.gov.**uk/terms/dri#transferAssethttp://nationalarchives.gov.uk/terms/dri#transferAsset ?transferAsset . } INSERT { ?transfer http://nationalarchives.gov.**uk/terms/dri#transferAssethttp://nationalarchives.gov.uk/terms/dri#transferAsset _:b0 . various triples with _:b0 as subject so the DELETE leaves the structure from the bNode in place even if unlinked? Ah, so are you saying we need to do something like: DELETE { ?transfer dri:transferAsset ?transferAsset . ?transferAsset ?property ?value . } INSERT { new transferAsset... } WHERE { ?transfer dcterms:identifier 201305241200^^xsd:string . ?subject dcterms:identifierdff82497-f161-4afd-8e38-**f31a8 b475b43^^xsd:string OPTIONAL { ?transfer dri:transferAsset ?transferAsset . ?transferAsset dcterms:subject ?subject ?transferAsset dcterms:modified ?transferAssetModified ; ?property ?value . FILTER (?transferAssetModified 2013-06-13T11:58:23.468Z^^xsd:dateTime) } } Otherwise the bNode gets orphaned? I can see this may be wrong but I'm not sure this would cause our problem which I believe is to do with the INSERT not being conditional on the filter statement. 2/ In the data: I see: .../transferAssetStatus#SENT but .../transferStatus#COMPLETED Whta's dri:transferAsset [ dri:transferAssetStatus .. vs dri:transferStatus Yes, I've probably given you too much information there. The transfer item also has status (as well as it's transferAssets) but this is unrelated the the problem. Thanks Rob
Re: Conditional INSERT statements
Immediate comments: 1/ DELETE { ?transfer http://nationalarchives.gov.uk/terms/dri#transferAsset ?transferAsset . } INSERT { ?transfer http://nationalarchives.gov.uk/terms/dri#transferAsset _:b0 . various triples with _:b0 as subject so the DELETE leaves the structure from the bNode in place even if unlinked? 2/ In the data: I see: .../transferAssetStatus#SENT but .../transferStatus#COMPLETED Whta's dri:transferAsset [ dri:transferAssetStatus .. vs dri:transferStatus Andy On 13/06/13 16:56, Rob Walpole wrote: Hi there, Hoping for some help with a SPARQL challenge I am facing... We have an instance of Jena Fuseki to which we POST SPARQL update queries to update the status of a thing called a transferAsset. A transferAsset is actually a bNode which is referenced by a thing called a transfer. These transferAssets have a subject, which is another resource, a status and a modified date. While there is a specific order in which status updates should be applied (e.g SENDING, SENT, COMPLETED) there is no guarantee of the order in which the updates will be received by Fuseki. In other words a COMPLETED status may inadvertently be received before a SENDING status. To check that we only apply the most recent status we check the modified date of the transferAsset. If the new modified date is later than the existitng modified date we delete the transferAsset at the same time as inserting a new one. The problem however is that although the deletion is conditional on there being a transferAsset older than the new transferAsset, the insert is not, and I am struggling to see how to make the insert conditional. This means that if the updates are received out of order we end up inserting another transferAsset with the same subject, i.e without deleting the old transferAsset - not what we want. The SPARQL code is shown below... DELETE { ?transfer http://nationalarchives.gov.uk/terms/dri#transferAsset ?transferAsset . } INSERT { ?transfer http://nationalarchives.gov.uk/terms/dri#transferAsset _:b0 . _:b0 http://purl.org/dc/terms/subject ?subject . _:b0 http://nationalarchives.gov.uk/terms/dri#transferAssetStatus http://nationalarchives.gov.uk/dri/catalogue/transferAssetStatus#SENT . _:b0 http://purl.org/dc/terms/modified 2013-06-13T11:58:23.468Z^^ http://www.w3.org/2001/XMLSchema#dateTime . } WHERE { ?transfer http://purl.org/dc/terms/identifier 201305241200^^ http://www.w3.org/2001/XMLSchema#string . ?subject http://purl.org/dc/terms/identifier dff82497-f161-4afd-8e38-f31a8b475b43^^ http://www.w3.org/2001/XMLSchema#string OPTIONAL { ?transfer http://nationalarchives.gov.uk/terms/dri#transferAsset ?transferAsset . ?transferAsset http://purl.org/dc/terms/subject ?subject . ?transferAsset http://purl.org/dc/terms/modified ?transferAssetModified FILTER ( ?transferAssetModified 2013-06-13T11:58:23.468Z^^ http://www.w3.org/2001/XMLSchema#dateTime ) } } And a sample transfer showing the duplication problem... http://nationalarchives.gov.uk/dri/catalogue/transfer/201305241200 rdf:type dri:Transfer ; dri:transferAsset [ dri:transferAssetStatus http://nationalarchives.gov.uk/dri/catalogue/transferAssetStatus#SENDING ; dcterms:modified 2013-06-13T11:58:23.463Z^^xsd:dateTime ; dcterms:subject http://nationalarchives.gov.uk/dri/catalogue/item/dff82497-f161-4afd-8e38-f31a8b475b43 ] ; dri:transferAsset [ dri:transferAssetStatus http://nationalarchives.gov.uk/dri/catalogue/transferAssetStatus#SENT ; dcterms:modified 2013-06-13T11:58:23.468Z^^xsd:dateTime ; dcterms:subject http://nationalarchives.gov.uk/dri/catalogue/item/dff82497-f161-4afd-8e38-f31a8b475b43 ] ; dri:transferStatus http://nationalarchives.gov.uk/dri/catalogue/transferStatus#COMPLETED ; dcterms:identifier 201305241200^^xsd:string ; dcterms:modified 2013-06-13T11:58:27.999Z^^xsd:dateTime . Many thanks