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. Important Considerations
    2. Example Use Cases
    3. Configuring Query Triggers
    4. Configuring the Webhook Endpoint
      1. Setup Process
      2. Webhook Security and Payload
    5. Triggers in Stardog Cluster
    6. Troubleshooting
    7. Example Usage
      1. Tracking Data Changes with Timestamps

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 that automatically notify external services when relevant data changes in your Stardog dataset.

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

Query triggers operate by:

  1. Executing stored queries on a defined schedule
  2. Comparing new results with previous results
  3. Sending notifications to a configured webhook endpoint when differences are detected

This feature eliminates the need to manually re-execute queries and compare results to detect changes in your data. Instead, Stardog handles this automatically, allowing you to focus on responding to the changes rather than detecting them.

Important Considerations

When creating query triggers, keep these technical details in mind:

  • Result Limiting: Every trigger query must have a maximum result size defined through the --trigger-limit option. Stardog will efectively add a LIMIT clause to the query. This limit controls how many results are tracked for changes.

  • Result Ordering: If the overall potential number of results exceed the defined limit, you should include an explicit ORDER BY clause in your query. Without it, the specific subset of results captured might be non-deterministic, potentially causing inconsistent trigger behavior.

  • Performance Optimization: For queries that don’t access external services or virtual graphs, Stardog optimizes performance by only re-executing the query when the underlying database has changed.

Example Use Cases

Query triggers are ideal for scenarios where you want automated notifications when specific patterns or conditions appear in your data. Examples include:

  • Business Rule Monitoring: Be notified when a customer places an order larger than any of their previous orders in the past 30 days
  • Quality Control Alerts: Receive alerts when more than 3 complaints about late deliveries are recorded for any supplier in the current quarter
  • Anomaly Detection: Get notifications when the volume of anomalies in any facility exceeds 2 standard deviations above the rolling 90-day average

Each of these scenarios can be implemented with a query trigger that evaluates the condition on a schedule and notifies your systems when the results change, enabling automated responses to important data events.

Configuring Query Triggers

To create a query trigger, use the stored add command with the following trigger-specific options:

Option Description
--trigger Enables the trigger functionality for this stored query
--trigger-schedule Defines execution frequency in seconds (e.g., 3600s for hourly)
--trigger-limit Maximum number of results to track for changes
--trigger-timeout Maximum execution time allowed for the query (e.g., 1m for one minute)

While the query itself can include a LIMIT clause, the --trigger-limit option is required to define the maximum result set size that will be tracked for changes.

Performance Considerations: Setting a very frequent schedule (e.g., 1 second) can potentially impact system performance, even though Stardog optimizes by only re-executing queries when data changes. As a best practice, configure schedule intervals appropriate to your use case — typically 300 seconds (5 minutes) or longer for most scenarios.

% 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                                                       |
+------------------------+-----------------------------------------------------------+

Configuring Trigger Payload

By default, trigger notifications only includes basic information. To include full query results in the webhook notification, use the --trigger-payload Full flag when creating your trigger:

stardog-admin stored add --trigger --trigger-payload Full --name your_trigger_name ...

This will include the complete query results in the notification payload sent to your webhook endpoint, allowing for more detailed processing of data changes.

Configuring the Webhook Endpoint

Each database with query triggers requires a single webhook endpoint configuration. The webhook is a REST endpoint that Stardog calls when query results change.

Setup Process

  1. Create a properties file with the webhook configuration:

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

    The filename pattern follows: trigger_webhook_<database_name>.properties

  2. Register the webhook using the data source management command:

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

    Note that Stardog repurposes the data source management system for webhook configuration.

Webhook Security and Payload

When a trigger detects changes, Stardog sends a POST request to your webhook URL with:

  1. A JSON payload containing metadata about the triggered query:

    {
      "name": "order_trigger",
      "database": "mydb",
      "timestamp": 1747916661851
    }
    
  2. An HMAC signature in the SD-Signature HTTP header to verify the request authenticity. This signature is computed using the trigger.secret value defined in your properties file.

For more information on implementing secure webhooks, see GitHub’s Webhook documentation.

Triggers in Stardog Cluster

When operating in a clustered environment, query triggers have specific behaviors to ensure reliability:

  • Execution Location: Triggers execute only on the primary coordinator node in the cluster
  • Endpoint Requirements: The webhook endpoint must be network-accessible from all Stardog nodes
  • Failover Behavior: During a coordinator failover:
    • The new primary node will re-execute active triggers
    • This may result in duplicate notifications for a single change
    • Systems consuming webhook notifications should implement idempotency handling

This architecture ensures trigger reliability even during cluster topology changes, though it may occasionally result in duplicate notifications that downstream systems should handle appropriately.

Troubleshooting

If your query triggers aren’t working as expected, follow this systematic troubleshooting approach:

  • Check trigger status using the stored get command:
     stardog-admin stored get your_trigger_name
    

    Look for error messages or unexpected configuration values in the output.

  • Verify webhook connectivity by confirming your webhook endpoint is:
    • Accessible from the Stardog server (check network/firewall settings)
    • Correctly configured to receive POST requests
    • Properly processing and acknowledging incoming requests
  • Review Stardog logs for detailed error messages related to trigger execution or webhook delivery

  • Validate your query by running it manually to ensure:
    • It executes without errors
    • It returns the expected results
    • It includes proper ORDER BY clauses if used with limiting
  • Check webhook configuration by confirming:
    • The trigger_webhook_<database>.properties file exists
    • The trigger.url property points to the correct endpoint
    • The trigger.secret value matches what your webhook service expects

Example Usage

Query triggers currently notify you when results change, but don’t automatically identify what specific data changed. To track specific changes, you need to implement additional logic that leverages timestamp properties in your data.

Tracking Data Changes with Timestamps

Consider this example of a social network tracking followers:

Data model includes timestamp information:

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

Create a trigger that monitors follower relationships with hourly checks:

stardog-admin stored add --name follower_trigger \
                        --database followers \
                        --trigger \
                        --trigger-schedule 3600s \
                        --trigger-limit 100 -- \
"SELECT * { ?follower :follows ?followed }"

When data changes (e.g., adding :Paul :follows :Simon; :since "2025-05-30"^^xsd:date .), the webhook receives a notification:

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

Execute a follow-up query that uses the notification timestamp to find recent changes:

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

Note: The ?timestamp variable must be converted to a proper dateTime value, not used as a raw numeric timestamp.

This pattern allows you to identify specific data changes by looking for records with timestamps that occurred after the previous trigger execution. While this approach may miss some changes in high-activity databases, it provides a practical foundation for change detection.