How to automatically generate new instance identifier in INSERT query on Sesame 2.7.7

159 views Asked by At

I'm facing the problem of identification when doing automatic instanciation of triplets using SPARQL queries. Let see the problem through this example.

suppose that we have the following triplets set representing person and their weeding relation.

ns:Person rdf:type        owl:Class
ns:Man    rdfs:subClassOf ns:Person
ns:Woman  rdfs:subClassOf ns:Person
ns:Family rdf:type        owl:Class

ns:jean  rdf:type ns:Man
ns:roger rdf:type ns:Man
ns:chris rdf:type ns:Woman
ns:sofy  rdf:type ns:Woman
ns:chloe rdf:type ns:Woman

ns:jean  ns:isMarriedWith ns:chris
ns:roger ns:isMarriedWith ns:chloe

Ok now we want to automatically build families using the rule that a family is when two person are married.

IF (ns:A ns:isMarriedWith ns:B) 
THEN (ns:f rdf:type Family) 
     AND (ns:f ns:contains A)
     AND (ns:f ns:contains B)    

here is the Java code that I propose to do that upon an http sesame repository.

Repository myRepository = new HTTPRepository(serverURL, repositoryId);
myRepository.initialize();
RepositoryConnection con = myRepository.getConnection();

query = "INSERT {" 
      + "   ns:f0 rdf:type    ns:Family ."
      + "   ns:f0 ns:contains ?p ."
      + "   ns:f0 ns:contains ?q ."
      + "}"
      + "WHERE { "
      + "   ?p ns:isMarriedWith ?q ."
      + "}";

Update update = con.prepareUpdate(QueryLanguage.SPARQL, query);    
update.execute();      

Here are triplets which were inserted

ns:f0 rdf:type    ns:Family
ns:f0 ns:contains ns:jean
ns:f0 ns:contains ns:chris
ns:f0 ns:contains ns:roger
ns:f0 ns:contains ns:chloe

This result is not correct, because only one family is created. The problem is that the identify of the familly instance doesn't change any time that the WHERE clause match.

How could I tune the above code in order the have the following correct response.

ns:f0 rdf:type    ns:Family
ns:f0 ns:contains ns:jean
ns:f0 ns:contains ns:chris
ns:f1 rdf:type    ns:Family
ns:f1 ns:contains ns:roger
ns:f1 ns:contains ns:chloe

Thank !

1

There are 1 answers

0
Joshua Taylor On BEST ANSWER

It's much easier to answer this type of question if you provide data and code that we can work with without having to add a whole bunch of stuff to make it complete. E.g., provide complete working RDF documents. Your data is something like this (in Turtle):

@prefix ns: <http://stackoverflow.com/q/20287293/1281433/> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> 

ns:Person a owl:Class .
ns:Man rdfs:subClassOf ns:Person .
ns:Woman rdfs:subClassOf ns:Person .
ns:Family a owl:Class .

ns:jean  a ns:Man .
ns:roger a ns:Man .
ns:chris a ns:Woman .
ns:sofy  a ns:Woman .
ns:chloe a ns:Woman .

ns:jean  ns:isMarriedWith ns:chris .
ns:roger ns:isMarriedWith ns:chloe .

In your SPARQL query, it's not clear what f0 is, since it's not legal SPARQL syntax, but based on your description of the problem, you've got something like the following. I've changed to a construct query so that we can look at the results of the query and see the triples that are constructed, which would be the same as the triples that get inserted. This just makes it easier to see what's happening.

prefix ns:    <http://stackoverflow.com/q/20287293/1281433/> 
prefix owl:   <http://www.w3.org/2002/07/owl#> 
prefix xsd:   <http://www.w3.org/2001/XMLSchema#> 
prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> 
prefix : <urn:ex:>

construct {
  :f0 a ns:Family .     # This can be written as 
  :f0 ns:contains ?p .  # :f0 a ns:Family ; ns:contains ?p, ?q .
  :f0 ns:contains ?q .  #
}
where {
  ?p ns:isMarriedWith ?q .
}

Now, your problem is that when you run this query on that data, you get results like:

:f0     a            ns:Family ;
        ns:contains  ns:chris , ns:jean , ns:chloe , ns:roger .

where there's one family that contains all four people, but you want a different family for each pair. The trick is to replace the constant :f0 with a blank node, which will be unique for each match in the query. You could do this just by changing :f0 to _:f0:

  _:f0 a ns:Family .   
  _:f0 ns:contains ?p .
  _:f0 ns:contains ?q .

but I'd prefer to use a bit more of the syntactic sugar that we have available to us and just write:

[ a ns:Family ; ns:contains ?p, ?q ]

so that we have:

prefix ns:    <http://stackoverflow.com/q/20287293/1281433/> 
prefix owl:   <http://www.w3.org/2002/07/owl#> 
prefix xsd:   <http://www.w3.org/2001/XMLSchema#> 
prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> 

prefix : <urn:ex:>

construct {
  _:f0 a ns:Family ; ns:contains ?p, ?q .
}
where {
  ?p ns:isMarriedWith ?q .
}

The results of this query contain two different families:

@prefix :      <urn:ex:> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ns:    <http://stackoverflow.com/q/20287293/1281433/> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

[ a            ns:Family ;
  ns:contains  ns:chris , ns:jean
] .

[ a            ns:Family ;
  ns:contains  ns:chloe , ns:roger
] .
<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:ns="http://stackoverflow.com/q/20287293/1281433/"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns="urn:ex:"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
  <ns:Family>
    <ns:contains rdf:resource="http://stackoverflow.com/q/20287293/1281433/chris"/>
    <ns:contains rdf:resource="http://stackoverflow.com/q/20287293/1281433/jean"/>
  </ns:Family>
  <ns:Family>
    <ns:contains rdf:resource="http://stackoverflow.com/q/20287293/1281433/chloe"/>
    <ns:contains rdf:resource="http://stackoverflow.com/q/20287293/1281433/roger"/>
  </ns:Family>
</rdf:RDF>