Reto Gmür
Reto Gmür

Reputation: 2647

SPARQL: Conditional INSERT

I'm trying to create a SPARQL statement that inserts some triples only if a certain pattern isn't yet in the graph.

PREFIX ssb: <ssb:ontology:>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

INSERT {
  <ssb:message/some=> rdf:type ssb:Message;
    ssb:seq 7;
    ssb:raw "some text";
    ssb:author 1.
} WHERE {
  FILTER NOT EXISTS {
    [] ssb:seq 7; ssb:author 1
  }
}

Unfortunately, this seems to create the new triples even if a resource with that ssb:seq and ssb:author already exist, tried the with quadstorejs and with oxigraph.

Any suggestion on how to perform such a conditional insert? The goal is that I don't end up with several resources having the same sequence number and author.

Upvotes: 1

Views: 290

Answers (2)

Pavel Klinov
Pavel Klinov

Reputation: 436

I believe your first attempt is correct and it looks like a bug in the systems that you tried.

The algebra for

  FILTER NOT EXISTS {
    [] ssb:seq 7; ssb:author 1
  }

is the FILTER directly on top of Singleton and it must return a single (empty) solution when the [] ssb:seq 7; ssb:author 1 does not match data. Since there're no variables in your INSERT template, data should be inserted.

The version with OPTIONAL isn't much different, there's an implicit {} before the OPTIONAL, and it's the same Singleton.

I just tried a CONSTRUCT version of your 1st query with Stardog and it worked as expected.

Upvotes: 2

Reto Gm&#252;r
Reto Gm&#252;r

Reputation: 2647

I found a solution that seems to work:

PREFIX ssb: <ssb:ontology:>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

INSERT {
  <ssb:message/some=> rdf:type ssb:Message;
    ssb:seq 7;
    ssb:raw "some text";
    ssb:author 1.
} WHERE {
  OPTIONAL {?x ssb:seq 7; ssb:author 1.}
  FILTER (!BOUND(?x))
}

Not sure exactly why, though. I mean the WHERE-Clause either matches nothing because the pattern isn't there or because it is filtered out when it exists.

Upvotes: 1

Related Questions