Link Search Menu Expand Document
Start for Free

Stored Queries

This page discusses managing stored queries in Stardog - the capability to name and store SPARQL queries for future evaluation.

Page Contents
  1. Overview
  2. Storing Queries
  3. Updating Stored Queries
  4. Importing and Exporting Stored Queries
  5. Running Stored Queries
  6. Listing Stored Queries
  7. Removing Stored Queries
  8. Stored Query Service


Stardog 4.2 added the capability to name and store SPARQL queries for future evaluation by referring to the query’s name.

Queries of any type can be stored in Stardog and executed directly by using the name of the stored query. Stored queries can be shared with other users, which gives those users the ability to run those queries provided that they have appropriate permissions for a database.

Stored queries can be managed via CLI, Java API, and HTTP API.

Storing Queries

Queries can be stored using the stored add Stardog admin command and specifying a unique name for the stored query:

$ stardog-admin stored add -n types "select distinct ?type {?s a ?type}"

If a file is used to specify the query string without an explicit -n/--name option then the name of the query file is used for the stored query:

$ stardog-admin stored add listProperties.sparql

By default, stored queries can be executed over any database, however, they can be scoped by providing a specific database name with the -d/--database option. Also, by default, only the user who stored the query can access that stored query. Using the --shared flag will allow other users to execute the stored query.


The following example stores a shared query with a custom name that can be executed over only the database myDb:

$ stardog-admin stored add --shared -d myDb -n listProperties "select distinct ?p {?s ?p ?o}"

Stored query names must be unique for a Stardog instance. Existing stored queries can be replaced using the --overwrite option in the command.

Updating Stored Queries

Queries can be updated using the --overwrite option on the stored add admin command and specifying an existing name for a stored query:

$ stardog-admin stored add --overwrite -n types "select distinct ?p {?s ?p ?o}"

Importing and Exporting Stored Queries

Stored queries are saved as RDF statements in the Stardog system database and it is possible to export the RDF representation of the queries:

Using the stored-export command:

$ stardog-admin stored export
@prefix system: <> .

system:QueryExportAll a system:StoredQuery , system:SharedQuery ;
   system:queryName "ExportAll" ;
   system:queryString """construct where {?s ?p ?o}""" ;
   system:queryCreator "admin" ;
   system:queryDatabase "*" .

system:QuerylistDroids a system:StoredQuery , system:ReasoningQuery ;
   system:queryName "listDroids" ;
   system:queryString "select ?x { ?x a :Droid }" ;
   system:queryCreator "luke" ;
   system:queryDatabase "starwars" .

The same RDF representation can be used to import the stored queries as an alternative way of storing new queries or updating existing stored queries.

Using the stored-import command:

$ stardog stored import queries.ttl

In addition to the built-in properties from the system database arbitrary RDF properties can be used for stored queries. The value of these additional annotation properties should be IRIs or literals. Only the values directly linked to the stored query subject in the RDF document will be saved and the triples with a non-stored query subject will be ignored.

Running Stored Queries

Stored queries can be executed using the regular query execution CLI command by passing the name of the stored query:

$ stardog query execute myDb listProperties

Other commands like query explainalso accept stored query names. They can also be passed instead of query string into HTTP API calls.

Listing Stored Queries

To see all the stored queries, use the stored list command:

$ stardog-admin stored list

The results are formatted tabularly:

|  Name  |            Query String                 |
| graphs | SELECT ?graph (count(*) as ?size)       |
|        | FROM NAMED stardog:context:all          |
|        | WHERE { GRAPH ?graph {?s ?p ?o}}        |
|        | GROUP BY ?graph                         |
|        | ORDER BY desc(?size)                    |
| people | CONSTRUCT WHERE {                       |
|        |    ?person a foaf:Person ;              |
|        |            ?p ?o                        |
|        | }                                       |
| types  | SELECT DISTINCT ?type ?label            |
|        | WHERE {                                 |
|        |    ?s a ?type .                         |
|        |    OPTIONAL { ?type rdfs:label ?label } |
|        | }                                       |

3 stored queries

Users can only see the queries they’ve stored and the queries stored by other users that have been --shared. The --verbose option will show more details about the stored queries.

Removing Stored Queries

Stored queries can be removed using the stored remove command:

$ stardog-admin stored remove storedQueryName

If you would like to clear all the stored queries then use the -a/--all option:

$ stardog-admin stored remove -a

Stored Query Service

Stardog supports a way to invoke stored queries, including Path Queries in the context of another SPARQL query using the SERVICE keyword. The Stored Query Service was released as beta in Stardog 7.3.2 and is generally availabile (GA) as of version 7.4.0. Previous versions of Stardog already employed the service mechanism in SPARQL to support full-text search and Entity Extraction and now this is naturally extended to stored queries.

Suppose, the following query is stored with the name “cities”:

$ stardog-admin stored add -n "cities" "SELECT ?country ?city { ?city :locatedIn ?country }"

Then it is possible to use it as a named view in another query:

prefix sqs: <tag:stardog:api:sqs:>

SELECT ?person ?city ?country {
    SERVICE <query://cities> { [] sqs:vars ?country, ?city }
    ?person :from ?city

This query uses the “cities” query to look up information about the country given the city where a person lives. It is similar to using a Wikidata endpoint or an explicit subquery except that the subquery is referenced by name. The same query with an explicit subquery would look like this:

SELECT ?person ?city ?country {
        SELECT ?country ?city {
            ?city :locatedIn ?country
    ?person :from ?city

Invoking stored queries by name has the major benefit that it avoids duplication of their query strings. Stored queries become reusable query building blocks maintained in one place rather than copy-pasted over the many queries which use them.

The body pattern of SERVICE <query://name> { ... } specifies which variables of the stored query are used in the outer scope of the calling query. The sqs:vars is a shortcut which is useful when stored query variables retain their names. However it’s possible to map stored query variable names to other identifiers to avoid naming conflicts:

prefix sqs: <tag:stardog:api:sqs:>

SELECT ?person ?city ?livesIn ?country {
    SERVICE <query://countries> {
        []  sqs:var:city ?livesIn ;
            sqs:var:country ?country
    ?person :from ?livesIn ;
            :born ?city

Furthermore, it’s possible to statically bind some stored query variables to constants so the query would behave like a parameterized view:

prefix sqs: <tag:stardog:api:sqs:>

SELECT ?city ?country {
    SERVICE <query://countries> {
        []  sqs:var:city ?city ;
            sqs:var:country :The_United_States

Another interesting feature is the ability to call path queries from SELECT/CONSTRUCT/ASK queries. One cannot directly use a path query in a subquery because those do not return SPARQL binding sets, aka solutions (we discussed that issue in an earlier blog post on Extended Solutions). However, this service circumvents that restriction:

prefix sqs: <tag:stardog:api:sqs:>

SELECT ?start (count(*) as ?paths) {
    SERVICE <query://paths> {
        [] sqs:vars ?start
} GROUP BY ?start

The stored path query returns paths (according to some VIA pattern) and uses ?start as the start node variable. The main query aggregates the returned paths by the start node and returns the number of paths for each. In contrast to the earlier SELECT example, this would not be possible directly because path queries cannot be used as subqueries.

One should be aware of the potential explosive nature of path queries when using them through the stored query service. They can return a very high number of paths to be joined or aggregated and thus create substantial memory pressure on the server.

Stardog 7.3.2+ supports two new SPARQL functions which take paths as the argument: stardog:length and stardog:nodes. The former returns the length of the path and the latter generates a comma-separated string of all path nodes. Since SELECT query results do not support paths as first-class citizens (that is, any value in a binding set is either an IRI or a literal or a blank node), these provide means to return path information by generating literals. Paths returned by the stored query service can be accessed via the reserved variable name ?path:

prefix sqs: <tag:stardog:api:sqs:>
prefix stardog: <tag:stardog:api:>

SELECT ?start (avg(stardog:length(?path)) as ?avg_length) {
    SERVICE <query://paths> {
        [] sqs:vars ?start, ?path
} GROUP BY ?start

Stardog 7.4.4 supports additional stardog:all and stardog:any functions to check Boolean conditions over edges in paths returned by a stored path query. These are useful for filtering path query results on the server side:

prefix sqs: <tag:stardog:api:sqs:>
prefix stardog: <tag:stardog:api:>

SELECT (str(stardog:nodes(?path))) {
    SERVICE <query://paths> {
        [] sqs:vars ?path
    FILTER(stardog:all(?path, ?attribute = 10))

Here ?attribute is a variable occurring in the VIA pattern of the stored path query. stardog:all returns true if the ?attribute = 10 condition is true for all edges in the path. The second argument can be an arbitrary SPARQL expression. stardog:any is the complementary function returning true if the condition is true for at least one edge. It is particularly useful for querying paths which must pass through a particular node(s) in the graph.