So, I have the following requirement: create a new instance of type A with label X, where X is unique for all instances of A.

Initially the way I implemented this feature was to execute an ASK query to check if an instance of A with rdfs:label X already exists. If so, ask the user for a unique label, otherwise execute the INSERT query. The problem with this approach is that the ASK query and the INSERT query are not atomic operations (I am currently using TDB/Fuseki for the triple store). During the time the ASK query is executed and the time the INSERT query is executed, a new instance of A could be created with the same label X.

What would be the best approach to make sure the uniqueness check and insert are an atomic operation?

What I have thought about is to do the uniqueness check and creation in the same query by having a filter in the Where clause, that would execute the insert only if the label is unique. After this query is executed, then I would execute another ASK query to check if the instance was created (if the instance was not created, then I know there is a duplicate label). The query would look something like this:

INSERT 
{
  ?newInstance a xyz:A .
  ?newInstance rdfs:label 'label here'^^xsd:string .
}
WHERE 
{   
    ?existingInstance a xyz:A  .
    ?existingInstance rdfs:label ?existingInstanceLabel .
    BIND (IRI(<xyz.com/instances/newInstance>) AS ?newInstance ) .
    FILTER (!regex(?existingInstanceLabel ,"^label here$","i")) .
}

This query would not work since the WHERE clause would get executed for any instance that does not match the new label.

This question is marked "community wiki".

asked 12 Dec '12, 14:57

Johnny's gravatar image

Johnny
12
accept rate: 0%

edited 12 Dec '12, 15:00


You can use FILTER NOT EXISTS to create a conditional INSERT of data. The WHERE clause of the update below evaluates to zero or one rows, so the template is executed zero or one times.

INSERT {
  <http://xyz.com/instances/newInstance> a xyz:A .
  <http://xyz.com/instances/newInstance> rdfs:label "LABEL" .
} WHERE {
    FILTER NOT EXISTS {
       ?existingInstance a xyz:A  .
       ?existingInstance rdfs:label "LABEL" . }
}
link

answered 13 Dec '12, 06:08

AndyS's gravatar image

AndyS ♦
13.0k37
accept rate: 32%

Something like this may work for you:

INSERT {
  <http://xyz.com/instances/newInstance> a xyz:A .
  <http://xyz.com/instances/newInstance> rdfs:label ?label .
} WHERE {
    OPTIONAL { <http://xyz.com/instances/newInstance>  rdfs:label ?existingInstanceLabel }
    BIND ( COALESCE(?existingInstanceLabel, "NEWLABEL") AS ?label
}

COALESCE is used to set the label to either the existing label or "NEWLABEL", preferring ?existingInstanceLabel.

link

answered 12 Dec '12, 16:14

AndyS's gravatar image

AndyS ♦
13.0k37
accept rate: 32%

edited 12 Dec '12, 16:16

Andy, thanks for your help but I don't think this works as I would like. Again, first I have to try to insert the new instance with a particular label X and only if an instance of the same class with the same label already exists, only then ask the user for a different label.

(12 Dec '12, 16:33) Johnny Johnny's gravatar image

Insert with a system-unique label that your code knows (e.g. a UUID string) at NEWLABEL so you get the old label or the one your code knows.

Query to find it again - if it is the UUID string, you know the label didn't exist. Ask the user for the string, and do a second update to remove the rdfs:label with the UUID string and put in what the user specifies.

(12 Dec '12, 16:44) AndyS ♦ AndyS's gravatar image

Andy, I think you miss-understood my requirement. I do NOT want to check whether my new instance already has a label, and if so don't overwrite it (which is what your query does). But what I want to do is check whether an existing instance of the same type as my new instance has the same label as the instance I want to create.

(12 Dec '12, 18:20) Johnny Johnny's gravatar image

For example assume I have a class Employee, and I have an existing Employee instance http://xyz.com/employees/employee1 with rdfs:label "John Doe". Now I want to create/insert a new Employee instance http://xyz.com/employees/employee2. If the rdfs:label of http://xyz.com/employees/employee2 is the same as the rdfs:label of http://xyz.com/employees/employee1 ("John Doe"), then the Insert clause should not be executed (do not create http://xyz.com/employees/employee2 since another instance of Employee with the same rdfs:label already exists)

(12 Dec '12, 18:20) Johnny Johnny's gravatar image
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×46

Asked: 12 Dec '12, 14:57

Seen: 931 times

Last updated: 13 Dec '12, 06:08