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. Renaming Stored Queries
  5. Attaching Arbitrary Properties to Stored Queries
  6. Importing and Exporting Stored Queries
  7. Running Stored Queries
  8. Listing Stored Queries
  9. Removing Stored Queries
  10. Security for Stored Queries
  11. Query Triggers
    1. Configuring Query Triggers
    2. Configuring the WebHook Endpoint
    3. Triggers in Stardog Cluster
    4. Troubleshooting
    5. Example Usage

Overview

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 they have appropriate permissions for a database).

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

Storing Queries

Queries can be stored using the stored add 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, 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.

EXAMPLE

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.

The attributes of stored queries are listed in the table below:

Attribute Description
Name The name of the stored query.
Query The query string to store.
Database The name of the database for this query. * is a special value to run the query over any database.
Creator The name of the user who stored the query.
Shared Boolean attribute if this query is shared by all the users.
Reasoning Boolean attribute if this query is going to be executed with reasoning enabled.
Schema The reasoning schema that will be used by this query, if reasoning is in use.
Annotations The additional annotations associated with the stored query.
Description The description field of the stored query.

These attributes can be leveraged with the options present in the stored add command, followed by the argument of the query to be stored.

Updating Stored Queries

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

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

Queries can also be updated with the stored set command:

$ stardog-admin stored set types -q "select ?p {?s ?p ?o}" -a urn:typeGroups="types"^^<http://www.w3.org/2001/XMLSchema#string> --reasoning on -d typesDb --

To retrieve attributes of stored queries, use stored get, optionally filtering annotations with the -a/--annotation option:

$ stardog-admin stored get types -a urn:typeGroups

results as:

+------------------------+-------------------------------------------------------------+
| Stored Query Attribute |                            Value                            |
+------------------------+-------------------------------------------------------------+
| Description            | a stored query for unit test                                |
| Query String           | select ?p {?s ?p ?o}                                        |
| Reasoning              | true                                                        |
| Database               | typesDb                                                     |
| Creator                | user                                                        |
| Shared                 | false                                                       |
| Name                   | types                                                       |
| Annotation             | urn:typeGroups="types"                                    |
+------------------------+-------------------------------------------------------------+

Renaming Stored Queries

Stored queries can be renamed using the stored rename command:

$ stardog-admin stored rename oldStoredQueryName newStoredQueryName

Attaching Arbitrary Properties to Stored Queries

In addition to the built-in properties from the system database, arbitrary RDF properties can be attached to stored queries. These properties can be supplied via options during or after creation of the stored queries. They can be specifically retrieved from the stored queries as well. 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.

During creation of a stored query, arbitrary properties are added via the -a or --annotation option as a list of key-value (IRI-RDF Value) pairs:

$ stardog-admin stored add -a prefix:iri=prefix:value -n queryName "select * {?s ?p ?o} order by ?s ?p ?o"

If a stored query’s properties need to be set after its creation, use the stored set command (with a comma delimiter if multiple pairs are supplied):

$ stardog-admin stored set queryName -a prefix:iri=prefix:value,prefix:another_iri=prefix:another_value --

Note that the usage above overrides the values if the keys are already present. However, if multiple values are needed per key, the --append option gives that flexibility:

$ stardog-admin stored set queryName -a prefix:iri=prefix:value --append --

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. To do so, use the stored export command:

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

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 stored queries. This is an alternative way to store new queries or update existing ones.

Using the stored import command:

$ stardog stored import queries.ttl

Running Stored Queries

Stored queries can be executed using the query execute command by passing the name of the stored query:

$ stardog query execute myDb listProperties

Query names can also be passed into other commands like query explain and into HTTP API calls in place of a query string.

Listing Stored Queries

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

$ stardog-admin stored list

The results are formatted as a table:

+--------+-----------------------------------------+
|  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, use the -a/--all option:

$ stardog-admin stored remove -a

Stardog supports a way to use stored queries as subqueries in larger SPARQL queries. For more details, see the Stored Query Service section and the blog post of the same name.

Security for Stored Queries

Stored queries can be read by their creators or users with superuser privileges, unless they are shared. In addition, stored queries can be deleted by their creators or users with superuser privileges. Shared stored queries can be read by any user.

A resource type exists for stored queries (in order to determine which users can store queries). Hence, the security aspect of stored queries is independent of database metadata. See Security Model for further details.

Query Triggers

Query Triggers are an extension of stored queries to notify external services of relevant changes to the Stardog dataset.

Beta Feature details of this feature might change in future releases.

Query triggers are stored queries that are executed on a schedule. The results of the query are compared to the previous results, and if they differ, a notification is sent to a configured webhook endpoint.

Previously, users had to manually re-execute graph queries and manually compare their results to the previous state to figure out when the relevant part of the data has changed. With this feature, Stardog automatically detects changes by executing the queries on demand.

Example Use Cases

As a user, I want to be notified when certain conditions exist in my data, such as:

  • A customer initiated an order larger than any of their past 30 orders
  • Received more than 3 complaints about a late delivery from any supplier in the last quarter
  • The total volume of anomalies in any of our facilities is more than 2 std deviations over the rolling average in the last 90d

All of these use cases can be implemented with a query trigger. The query trigger will execute the query on a schedule and notify a REST endpoint when the results change.

Configuring Query Triggers

To create a query trigger, use the --trigger option with the stored add command. The --trigger-schedule option specifies how often (in seconds) the query will be executed, and the --trigger-limit option specifies how many results will be watched for changes. An additional LIMIT in the query itself is not required, but it can be used to limit the number of results returned by the query further.

Please note that the schedule option will influence the frequency of the query execution, therefore picking a very small value (e.g. 1 second) will potentially result in a lot of queries being executed. Queries are only re-executed whenever Stardog detects a data change, but this is may still lead to performance issues. A good practice is to set the schedule to a value that is appropriate for the use case, such as 300 seconds or more.

% stardog-admin stored add --name triggername \
                           --database mydb \
                           --trigger \
                           --trigger-schedule 3600s \
                           --trigger-limit 100
                           --trigger-timeout 1m -- \
   "PREFIX : <http://stardog.com/orders/> SELECT * {  ?s a :ProductType; :createdDate ?date;  :name ?name  } ORDER BY ?date"

You can see the details of the trigger execution via the stored get command. The output might also show details about the trigger execution state.

% stardog-admin stored get triggername

+------------------------+-----------------------------------------------------------+
| Stored Query Attribute |                           Value                           |
+------------------------+-----------------------------------------------------------+
| Name                   | triggername                                               |
| Query String           | select * {?s ?p ?o} order by ?s ?p ?o                     |
| Database               | mydb                                                      |
| Reasoning              | false                                                     |
| Shared                 | false                                                     |
| Creator                | testuser                                                  |
| Trigger                | Yes                                                       |
| Trigger Limit          | 100                                                       |
| Trigger Frequency      | 3600s                                                     |
| Trigger Timeout        | 60s                                                       |
+------------------------+-----------------------------------------------------------+

Trigger Payload

The stored add --trigger-payload Full flag may be used to configure a full payload for the trigger. The payload will be included in the notification sent to the webhook endpoint.

Configuring the WebHook Endpoint

For each database that has Stored Queries with triggers, you may configure one webhook endpoint. A webhook is a simple REST endpoint that Stardog will call when the results of a query change. The webhook can be any REST endpoint that accepts POST requests.

To configure the webhook endpoint, create a data source with the name of the database with a trigger_webhook_ prefix. For example, for a database mydb, create a data source with the name trigger_webhook_mydb.

Create a trigger_webhook_mydb.properties file for the data source like the following:

% cat trigger_webhook_mydb.properties
trigger.url=http://localhost:3000/log
trigger.secret=ABCD

Use the stardog-admin data-source add CLI command to register the webhook:

% stardog-admin data-source add ./trigger_webhook_mydb.properties

Stardog repurposes the stardog-admin data-source command to add the webhook configuration. The webhook will be called with a JSON payload containing the results of the query.

% cat endpoint.properties
trigger.url=http://localhost:3000/log
trigger.secret=ABCD

% stardog-admin data-source add -n trigger_webhook_mydb ~/Desktop/endpoint.properties

A webhook request body will for example look like this:

{"name":"order_trigger","database":"mydb","timestamp":1747916661851}

Additionally we include an HMAC signature in the SD-Signature header, which can be used to verify the authenticity of the request. The signature is computed using the trigger.secret property and the request body. For more information on webhooks, see GitHub’s Webhook documentation.

Triggers in Stardog Cluster

In a Stardog cluster, query triggers are executed on the primary coordinator node. The results of the query are then sent to the webhook endpoint configured for the trigger. The endpoint must be reachable by all Stardog nodes. In the event of a failover, the trigger will be executed on the new coordinator node. The trigger might be executed multiple times during a failover, as the new primary node will re-execute the trigger to ensure that the latest results are sent to the webhook endpoint.

Troubleshooting

The status of the query trigger can be checked using the stored get command. If the trigger is not working as expected, check the following:

  • Check for error messages in the stored get output.
  • Ensure that the webhook endpoint is reachable from the Stardog server.
  • Check the Stardog logs for any errors related to the trigger execution.
  • Verify that the query is valid and returns results.
  • Ensure that the trigger.url and trigger.secret properties are set correctly in the endpoint configuration file.

Example Usage

The query trigger feature will currently only tell you when results change, but not what changed. Suppose you want to know what triples were added or removed, then you need to implement that logic yourself. One could achieve this by adding date-time properties to your data.

For example you have a followers database, containing triples about users and their followers.

:Paul :follows :Evren; 
      :since "2025-01-01T00:00:00Z"^^xsd:dateTime .

and a stored query with an 1h trigger frequency:

SELECT * {
  ?follower :follows ?followed
}

Adding a new follower :Paul :follows :Simon ; :since "2025-05-30"^^xsd:date . should trigger a webhook notification, with a payload like this:

{
  "name": "follower_trigger",
  "database": "followers",
  "timestamp": 1747916661851
}

Now we can detect new followers by using the timestamp property in the webhook payload. Note ?timestamp has to be a dateTime value, not a timestamp. This might still miss some changes if there is a lot of activity in the database, but it is a good starting point.

SELECT * {
  ?follower :follows ?followed .
  ?follower :since ?since .
  FILTER(?since >= (?timestamp - xsd:duration('PT1H')))
}