Binding Multiple Values

Blog

Binding Multiple Values

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

With MarkLogic’s SPARQL queries, we can bind a value to constrain the query. Using this capability, we can gather information about something of interest. But what if I want to query against multiple values?

Let’s start with some sample data.

'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))
 )

After running this in Query Console, I have 10 triples. Now suppose I want to find the objects where the subject is one of target1target2, or target3? I have a couple choices. With MarkLogic, I can go after one of these values with a simple bind (the second parameter in sem.sparql):

sem.sparql(
  `
    select ?obj
    where {
      ?target ?pred ?obj
    }
  `,
  { target: sem.iri("target1") }
)

To be complete in thinking about my options, I could brute-force it and just run multiple SPARQL queries, one for each of my targets. That’s pretty inefficient.

I could also use a FILTER.

sem.sparql(
  `
    select ?ojbj
    where {
      ?target ?pred ?obj
      FILTER (?target IN (<target1>, <target2>, <target3>))
    }
  `
)

This is effective, but I’ve learned it’s not very efficient (but better than multiple queries). Another option is to bind the values we’re looking for using sem.sparql‘s second parameter:

'use strict';
sem.sparql(
  `
    select ?obj
    where {
      ?target ?pred ?obj
    }`,
  {
    target: [sem.iri("target1"), sem.iri("target2"), sem.iri("target3")]
  }
)

I loaded up my database with 100,000 triples for a quick test (no other data, no other load). Both ran in a matter of milliseconds, but using the bind approach ran in about a quarter of the time that the FILTER approach took.

If you’re looking to run a SPARQL query and you want to use multiple values, binding an array is the preferred way. Interesting to note, however — you can’t do that in a SPARQL update! Stay tuned for the next post where I’ll cover that.

Share this post:

2 replies on “Binding Multiple Values”

Hey Dave,
Thanks for this post, it helped me solve a bindings problem I was having where I was getting the dreaded “BADRDFVAL” deep inside my sparql endpoint. Playing around with your example I found out what was wrong with mine.

For what its worth, I was trying to return the target with the associated data. I had a BIND() that caused the bad rdf value.

I was using ?target as an object, and trying to bind it into the results.

BIND(?target as ?returnVar) # <– fails bad-val

What worked?
select ?trade ?trader ?ts …
?trade  a             ?tradeType;
         xxx:tradeDate  ?ts;        
         xxx:trader     ?trader ;     # binds up the trader for return
         xxx:trader     ?target .    # member ship in our target’s bindings

This worked and avoided using sem.sparqlValues() which has an ugly syntax imho.

From what I can tell, there is no way to do this sort of thing directly in a SPARQL without having a VALUES statement. So this raises the question: Is ML invoking the SPARQL multiple times, once for each ?target array member creating a union of the results?

Please share any guesses or insights!
Cheers,
Derek

Hi Derek, thanks for posting. I’ve been thinking about your question but I don’t have an answer. I’m wondering whether there’s a trace flag that might give an answer. The semantics.xqy library doesn’t have any xdmp:trace calls in it that I can see, nor do the files in the semantics directory. If I can track down an answer I’ll let you know; please do the same!

cta-bg

Ready to Chat?

Book your 30-minute Technology Clarity Call. I offer a free, no-obligation consultation to learn about your business and explore whether a Fractional CTO engagement is the right fit.