SPARQL update with multiple targets

Blog

SPARQL update with multiple targets

  • 28 July, 2022
  • By Dave Cassel
  • No Comments
blog-image

In my last post, I talked about using the bindings parameter of MarkLogic’s sem.sparql function to look for multiple values in a SPARQL query. It turns out that approach doesn’t work for SPARQL Update.

I’ll use the same sample data as my previous post:

'use strict';
declareUpdate();
const sem = require("/MarkLogic/semantics")
const myPred = sem.iri("myPredicate");
sem.rdfInsert([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  .map(num => sem.triple(sem.iri(`target${num}`), myPred, num))
)

Now suppose that I want to delete some of those values. I’ll go after the triples with subjects target1target2, and target3. Let’s try the same approach that works for queries and bind these values as a parameter to the query:

'use strict';
const myPred = sem.iri("myPredicate");
const targets = [sem.iri("target1"), sem.iri("target2"), sem.iri("target3") ];
sem.sparqlUpdate(
  `
    delete {
      ?target <myPredicate> ?obj
    }
    where {
      ?target <myPredicate> ?obj
    }
  `,
  {
    target: targets
  }
)

When I run this, I get an error: XDMP-BADRDFVAL. Uh oh, a bad RDF value. I expect the where clause here works the same as a SPARQL query, but ?target and ?obj get bound and used in the delete clause. That clause doesn’t like the array. Alright, how can we do this instead?

I’ve found that using SPARQL’s VALUES clause works.

'use strict';
const myPred = sem.iri("myPredicate");
const targets = [sem.iri("target1"), sem.iri("target2"), sem.iri("target3") ];
sem.sparqlUpdate(
  `
    delete {
      ?target <myPredicate> ?obj
    }
    where {
      ?target <myPredicate> ?obj
      VALUES ?target { ${targets.map(iri => '<' + iri + '>').join(' ')} }
    }
  `
 )

Let’s take a closer look at that VALUES line. The SPARQL is wrapped in ` (backtick), so we can do string interpolation. I’m wrapping the individual values in ‘<‘ and ‘>’ so that they’ll be seen as IRIs. What the interpreter will see is this:

delete {
  ?target <myPredicate> ?obj
}
where {
  ?target <myPredicate> ?obj
  VALUES ?target { <target1> <target2> <target3> } }
}

This allows me to hit multiple targets with my delete in the same request.

There is one thing I don’t like about this approach: when we’re using the binding parameter, the actual query string that we’re passing in remains the same for different calls. MarkLogic can interpret the query, build a plan, and cache it in anticipation of the query being called again (like any parameterized query). With this approach, the query itself changes every time it gets called, so caching doesn’t help us. All the same, it works.

Found a better way? Let me know in the comments!

quote
In my last post, I talked about using the bindings parameter of MarkLogic’s sem.sparql function to look for multiple values in a SPARQL query....
0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
cta-bg

Looking Forward to Building a Partnership!

Let's discuss how we can help your organization