Reputation: 2647
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
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
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