SNaidra
SNaidra

Reputation: 41

Create a unique id for a whole SPARQL query

I need a unique id (uuid) for a whole query independent of the number of matches.

Consider the following Data

@prefix ex:<http://www.example.org/>
ex:John ex:knows ex:Kathrin.
ex:John ex:knows ex:Peter.
ex:John ex:worksAt ex:coolShop.

The data tells us that John knows some people and works at coolShop.

Now we have an INSERT query:

1   PREFIX ex:<http://www.example.org/>
2   INSERT{
3     ?john ex:knows         ex:Alan.
4     ?john ex:hasRandomUUID ?uuid.
5   }
6   WHERE{
7     ?john ex:knows ?friend.
8     OPTIONAL{
9       ?john ex:worksAt ?shop
10      BIND(STRUUID() AS ?uuid)
11     }
12   }

This query inserts that john knows Alan. Furthermore, I want to insert a unique id for John denoted by ?john ex:hasRandomUUID ?uuid. But I want to add this unique id only if John works somewhere. Therefore, we bind BIND(STRUUID() AS ?uuid) in the optional clause. So if ?john ex:worksAt ?shop matches we bind an unique id to ?uuid. (Assume that a person can only work at on place at once and assume that there may be more than one triple in the optional clause.)

So far so good.

My problem now is that due to the fact that ?john ex:knows ?friend in line 7 matches twice, BIND(STRUUID() AS ?uuid) is evaluated twice and thus, 2 different uuids are generated. Due to the fact that 2 different uuids are generated, two triples of the form ex:John ex:hasRandomUUID uuid are inserted even though I only want one. How can I make sure that only one uuid is created independently from any matches or that only one triple of the form ex:John ex:hasRandomUUID uuid is inserted.

Please not that I cannot use something like Bind(ex:John AS ?john) instead of line 6.

I work with Apache Jena Fuseki.

Thank you very much.

EDIT: This worked for me:

1   PREFIX ex:<http://www.example.org/>
2   INSERT{
3     ?john ex:knows         ex:Alan.
4     ?john ex:hasRandomUUID ?uuid.
5   }
6   WHERE{
7     ?john ex:knows ?friend.
8     {
9       OPTIONAL{
10        ?john ex:worksAt ?shop
11        BIND(STRUUID() AS ?uuid)
12      }
13    }
14  }

By adding line 8 and line 13 the whole OPTIONAL clause is put in a sub query. This leads to STRUUID() being evaluated only once and only on triple of the form ex:John ex:hasRandomUUID uuid is inserted in the dataset.

Upvotes: 1

Views: 926

Answers (1)

AndyS
AndyS

Reputation: 16700

One approach is to allocation the potential ID when the query matches ?john then assign it to the actual variable when it is needed:

WHERE
  {
    ?john ex:knows ?friend .
    BIND ( STRUUID() AS ?uuidX )
    {
      OPTIONAL
        {
          ?john ex:worksAt ?shop .
          BIND ( ?uuidX AS ?uuid )
        }
    }
  }

Upvotes: 3

Related Questions