Templated SPARQL Queries

Hello,

The ability to save queries in the database and simply call a URL with the query name in it is really nice.

However, sometimes I want to publish a query that may take a parameter, for example, a string passed to <tag:stardog:api:property:textMatch>

What if you could store a SPARQL query as a template, where the templated items are exposed as parameters in the URL. Something like this:

http://localhost:5820/myDB/query/myQuery?query_template=someString

Cheers,

Nolan

I'm not quite sure exactly what you're looking to do but I think you can do what you're looking for is bindings. I don't think that the stored queries url is quite qhe you sent but you can execute a stored query through the normal query interface but just give the name instead of the "select * where...." and then pass some initial bindings. I don't think the final url will be very pretty though.

Hi Nolan,

This functionality already exists, though I will admit it's not documented very well at the moment. Just a couple of gotchas:

  1. Your stored query should have variables that start with a $ instead of a ? so the ?s don't get caught up in the URL parser
  2. The query string parameters should also have the $

Example:
Query: select $s $p { $s a :Thing; $p $o }
URL: http://myStardog:5820/myDb/query?query=myStoredQuery&$s=<some:uri> (well actually it'd be ...?query=myStoredQuery&%24s%3D%3Csome%3Auri%3E, but I went for readability)

Hey Zachary and Stephen,

Thanks for this info, great to hear that this is already implemented! And yes, I was a little lazy with the syntax in my post, Stephen's post clarified that though.

I think I still have an issue, however. Does this only work with a URI or could it work with a string?

For example, take the query:

 SELECT DISTINCT ?s ?score
 WHERE {
   ?s ?p ?l .
   (?l ?score) <tag:stardog:api:property:textMatch> '$search' .
}

If I execute that using the following curl-like request:

http --auth admin:admin 'http://localhost:5820/all/query?query=paramaterized-string-search&$search=foo'

I see the following:

HTTP/1.1 400 Bad Request
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 84
Content-Type: application/json
Date: Thu, 25 Oct 2018 01:43:21 GMT

{
    "message": "The query binding 'foo' is a malformed Turtle value"
}

Any idea what I am missing here?

The value needs to be a syntactically valid constant term. Stepping back for a second, the value will be substituted for a variable in your query. However, '$search' is not a variable, it is a string constant. You need to remove the quoting, ie $search. That said, it should now make sense that the bound value will be substituted for that variable. The bound value can be a string, such as 'foo' (note the quotes), an IRI <tag:stardog:...>, etc. So you need to remove the quotes around '$search' and add them around foo.

Best,
Jess

Hey Jess,

Not sure I follow, $string is not a SPARQL variable, but ?search would be. I thought using the $ denoted a special template keyword that was just replaced by the parameter passed through in the URL.

However, I did try what you suggested. When I go to save this query in Studio I get the following:

If I add the quotes, I have no problem saving. Any chance you can replicate that (I haven't tried from the CLI)?

Can you give an example of what would work?

It looks like the bug is creating a stored query with the textMatch property function using a variable for the search query. I'll create a new ticket for this. This query is not valid in general without a bound value.

In the interim, you can still accomplish the same thing without a stored query:

$ stardog query explain db -b search='"food"' --  'select * { $s $p $l . (?l ?score) <tag:stardog:api:property:textMatch> $search . }'
Explaining Query:

select * { $s $p $l . (?l ?score) <tag:stardog:api:property:textMatch> $search . }
# Overrides by the API:
# PARAMETERS ( ?search ) {
# "food"
# }

The Query Plan:

Projection(?s, ?p, ?l, ?score, ?search) [#1]
`─ Bind("food" AS ?search) [#1]
   `─ MergeJoin(?l) [#1]
      +─ Sort(?l) [#1]
      │  `─ Full-Text(query="food") -> (result=?l, score=?score) [#1]
      `─ Scan[OSP](?s, ?p, ?l) [#1.1K]

Note that I quoted the bind value twice. Once for the shell and once to make it a string literal.

Jess

Just a point of clarification here, but $string actually would be a SPARQL variable, as both are acceptable according to the spec.

@stephen, woa thanks for pointing that out... I have always seen SPARQL variables written with a question mark, had no idea that is in the spec and a dollar symbol can be used.

For these template queries, is there any difference between using the ? or $ when constructing a URL to execute the query? It seems like including the variable prefix symbol could be omitted, similar to how in the CLI the binding just uses the variable name search, not $search: stardog query explain db -b search='"food"'

@Jess thanks for filing a ticket. I think this would be pretty handy to have work.