Binding Multiple Values

Blog

Binding Multiple Values

  • 28 July, 2022
  • By Dave Cassel
  • 1 Comment
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:

quote
With MarkLogic’s SPARQL queries, we can bind a value to constrain the query. Using this capability, we can gather information...

4V Services works with development teams to boost their knowledge and capabilities. Contact us today to talk about how we can help you succeed!

0 0 votes
Article Rating
Subscribe
Notify of
1 Comment
Inline Feedbacks
View all comments

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

cta-bg

Get In Touch

Wherever you are in your data management journey, we're here to help you take the next step. Whether you're just starting to identify challenges or are ready to implement a solution, our team is ready to assist.