Querying

Carbon LDP™ resources can be queried using SPARQL, a W3C standard query language.

SPARQL has some similarities to SQL, the Structured Query Language for relational databases, but there are also fundamental differences. The main difference with SPARQL is that, instead of filtering results to get a desired outcome (like in SQL), you apply patterns that are tested over the data to retrieve results. These patterns are given along with query form to define the shape of the results.

There are four different query forms:

  • SELECT
    Returns the matched data in a table-like structure
  • ASK
    Returns true or false indicating whether data matched the pattern(s)
  • CONSTRUCT
    Restructures the matched data into a graph described by a specified template
  • DESCRIBE
    Returns a description of how the data is internally stored

A pattern is defined by using three elements:

  1. Resource: any document, fragment or named fragment referenced by a URI
  2. Property: the name or URI of a property of the resource
  3. Value: the value of the property

For example, if we wanted to match a document that represented a project, which has the property name with the value "Project X", we could use the pattern:

  1. Resource: projects/project-01/ (the project’s ID/URI)
  2. Property: name
  3. Value: "Project X"

This example pattern fully defines all of its elements. Each pattern element has the exact value we’re trying to match. But querying involves retrieving more data than we already have, so each pattern element can also be a variable.

A variable acts like a wildcard, matching any values the pattern element can have. But unlike wildcards, a variable stores any value it matches (you can think of them kind of like the columns requested on SQL queries).

E.g: To query the name of a project you would only need the project’s URI (resource) and the name (property). The value would be represented by a variable in which you will obtain the data you queried for.

SPARQL Query Builder

The SDK integrates our own query builder called SPARQLER (SPARQL query buildER) which offers a fluent interface to help you construct queries and prevent errors by malformed patterns.

Currently, we only support SELECT and ASK queries with SPARQLER.
We intend to extend the builder to cover more features in a subsequent release.

 

To create a query you must call the method $sparql( documentURI:string ) of the documentsendpoint along with the document URI to query against.

If you already have a Document you can also call its $sparql() method, to query directly on it.

let carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "resource-end-point/" )
    // ... query construction
    ;


let document;
// ... get the persisted Document
document.$sparql()
    // ... query construction
    ;
import { Document } from "carbonldp/Document";

let carbonldp:CarbonLDP;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "resource-end-point/" )
    // ... query construction
    ;


let document:Document;
// ... get the persisted Document
document.$sparql()
    // ... query construction
    ;
var carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "resource-end-point/" )
    // ... query construction
    ;


var document;
// ... get the persisted Document
document.$sparql()
    // ... query construction
    ;

ASK Query

General structure

SPARQL ASK queries have the following structure and order:

  1. Specify that the type of query is an ask query with the method:
    • .ask()
  2. Optionally, you can specify in which document the query will be performed using:
    • .from( ... )
    • .fromNamed( ... )
  3. Specify the patterns to match:
    • .where( ... patterns )
  4. Add optional solution modifiers:
    • .groupBy( ... )
    • .having( ... )
    • .orderBy( ... )
    • .limit( ... )
    • .offset( ... )
  5. Optionally filter your results with a given value:
    • .values( ... )
  6. And finally execute the query:
    • .execute()

Pattern Matching Building Tools

Carbon offers several methods in order to make your query more specific on what you want to retrieve. You can read more information on the pattern matching building tools section.

Solution Modifiers

Once your query returns its solutions, you can use one of Carbon’s methods to modify them. You can read more about them in the solution modifiers section.

SELECT Query

General structure

SPARQL SELECT queries have the following structure and order:

  1. Select what data to include in the response:
    • .select( ... variables)
    • .selectAll()
    • .selectDistinct( ...variables)
    • .selectAllDistinct()
    • .selectReduced( ...variables)
    • .selectAllReduced()
  2. Optionally, you can specify in which document the query will be performed using:
    • .from( ... )
    • .fromNamed( ... )
  3. Specify the patterns to match:
    • .where( ... patterns )
  4. Add optional solution modifiers:
    • .groupBy( ... )
    • .having( ... )
    • .orderBy( ... )
    • .limit( ... )
    • .offset( ... )
  5. Optionally filter your results with a given value:
    • .values( ... )
  6. And finally execute the query:
    • .execute()

Data Selection

We can specify which variables to be included by using one of these methods:

  • .select( ...variables:string[] ). Specify which variables used in the pattern(s) will be returned with the query result
  • .selectAll(). Indicate that all variables used in the pattern(s) will be included in the result
  • .selectDistinct( ...variables:string[] ). Set a list of variables to be retrieved by the query ensuring no repetitions in the set of solutions.
  • .selectAllDistinct(). Set that the query must return all the solutions for the variables used in the pattern(s), ensuring there is not duplicated solutions.
  • .selectReduced( ...variables:string[] ). Set a list of variables to be retrieved by the query permitting eliminations of non-distinct solutions, but not ensuring a set of unique ones.
  • .selectAllReduced(). Set that the query must return all the solutions for the variables used in the pattern(s), permitting eliminations of non-distinct solutions, but not ensuring a set of unique ones.

Pattern Matching Building Tools

Carbon offers several methods in order to make your query more specific on what you want to retrieve. You can read more information on the pattern matching building tools section.

Solution Modifiers

Once your query returns its solutions, you can use one of Carbon’s methods to modify them. You can read more about them in the solution modifiers section.

Pattern Matching Building Tools

Optionally, you can select a default document to be used in the search for the query solutions using:

  • .from( iri:string ). Set a default document or documents as the dataset where to look for the query solutions.
  • .fromNamed( iri:string ). Set a named document to be included as the Dataset where to look for the query solutions.

If several from() methods are used, the query is executed in the merge of all the documents specified. The documents specified by the fromNamed() method are only queried with the instructions inside a graph pattern.

In the case of the pattern to match, it’s a little different since you need to provide a function where you can construct the pattern:

  • .where( patternFunction:( builder:PatternBuilder ) => GraphPattern ). A single pattern to match
  • .where( patternFunction:( builder:PatternBuilder ) => GraphPattern[] ). Multiple patterns to match

As you can see, the patternFunction receives a SPARQL/PatternBuilder object which contains helper properties and functions to construct the patterns you need.

Additionally, like in the Document Reader, you can use the values()method in order to combine values in the result of the query, there are 4 variations of this method:

  • .values( variable:string, values:SupportedNativeTypes | SupportedNativeTypes[] ): Set the values of a variable to be combined into the results query.
  • .values( variable:string, valuesBuilder:( builder:PatternBuilder ) => (SupportedNativeTypes | Resource | Literal | Undefined) | (SupportedNativeTypes | Resource | Literal | Undefined)[] ): The values of the variable are constructed with a function that receives a pattern builder.
  • .values( variables:string[], values:SupportedNativeTypes[] | SupportedNativeTypes[][]): Set the values of multiple variables to be combined into the results query.
  • .values( variables:string[], valuesBuilder:( builder:PatternBuilder ) => (SupportedNativeTypes | Resource | Literal | Undefined)[] | (SupportedNativeTypes | Resource | Literal | Undefined)[][] ): The values of the variables are constructed with a function that receives a pattern builder.

The .values() method can be used both inside and outside the where() method. If it is used inside the where clause, the values are combined inside the query, however, if it is used outside, the values are combined after the query has retrieved the results

SupportedNativeTypes are JavaScript’s types boolean, number, string and Date

Example

Assuming we had the following object stored:

// Representation of the stored object
{
        // Document URI
        "@id": "http://localhost:8083/projects/project-01/",

        // Properties
        "name": "Project X",
        "startDate": "2017/02/19"

        // ...
}

The following query would retrieve the values of the name and startDate property:

let carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/project-01/" )
    .select( "projectName", "projectStart" )
    .where( _ => {
        return _.resource( "projects/project-01/" )
            .has( "name", _.var( "projectName" ) )
            .and( "startDate", _.var( "projectStart" ) );
    } )
    .execute()
    .then( ( results ) => {
        console.log( results );
    } );
import { PatternBuilder } from "sparqler/patterns";
import { SPARQLSelectResults } from "carbonldp/SPARQL";

let carbonldp:CarbonLDP;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/project-01/" )
    .select( "projectName", "projectStart" )
    .where( ( _:PatternBuilder ) => {
        return _.resource( "projects/project-01/" )
            .has( "name", _.var( "projectName" ) )
            .and( "startDate", _.var( "projectStart" ) );
    } )
    .execute()
    .then( ( results:SPARQLSelectResults ) => {
        console.log( results );
    } );
var carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/project-01/" )
    .select( "projectName", "projectStart" )
    .where( function( _ ) {
        return _.resource( "projects/project-01/" )
            .has( "name", _.var( "projectName" ) )
            .and( "startDate", _.var( "projectStart" ) );
    } )
    .execute()
    .then( function( results ) {
        console.log( results );
    } );

The query can be translated to:

  • Search for a resource that has the id projects/project-01/
  • This resource must have a property name with any value(s)
    • Store those values in the projectName variable
  • The resource must also have the property startDate with any value(s)
    • Store those values in the projectStart variable
  • Return me the values stored in the variables projectName and projectStart

In this example we are using the var( variableName ) function of the helper object _ to declare two variables:

  • projectName
  • projectStart

These variables must appear in the pattern to match so they can be assigned values.

In the .where() method, we use the PatternBuilder to first indicate we are targeting a resource with the URI: projects/project-01/, and as the URI is relative, it will be automatically resolved to http://localhost:8083/projects/project-01/ (assuming the platform’s host is http://localhost:8083/).

From this resource we call the has() method, to indicate that the resource must have a property called name, with value(s) bound to the variable projectName.

Next we call the and() method, stating that it also needs to have a property startDate, with value(s) bound to the variable projectStart.

Example

To retrieve the name and start date from all available projects, we need to consider the following:

  • The end-point of the query must be the container of the projects: projects/
  • The children of the container are under the property: http://www.w3.org/ns/ldp#contains
  • We need to bind every child document (project) and ask for its name and start date, as in the previous example
let carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( _ => {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .execute()
    .then( ( results ) => {
        console.log( results );
    } );
import { PatternBuilder } from "sparqler/patterns";
import { SPARQLSelectResults } from "carbonldp/SPARQL";

let carbonldp:Carbon;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( ( _:PatternBuilder ) => {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .execute()
    .then( ( results:SPARQLSelectResults ) => {
        console.log( results );
    } );
var carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( function( _ ) {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .execute()
    .then( function( results ) {
        console.log( results );
    } );

As we can see, the major difference is that we return of an array of patterns. The first pattern matches the child documents from the projects/ container and binds them to the everyProject variable. With this variable we can then ask for the name and start date of every corresponding project.

There are several methods which help you construct a more complex pattern, some of them were used in the example above:

  • .resource( iri:string ): Creates a resource from the IRI or prefixed name specified.
  • .var( name:string ): Cretes a variable from the name specified.
  • .literal( value:string | number | boolean ): Creates a literal from the value specified.
  • .collection( ...values:(SupportedNativeTypes | Resource | BlankNode | Variable | Literal | Collection | BlankNodeProperty)[]: Creates a collection from all the values provided.
  • .blankNode( label?:string ): Creates a bNode reference from the label specified.

.has() and .and() are compatible with all of these methods.

Alongside with this methods, the query builder also provides some SPARQL direct methods and properties, which generate other patterns:

  • .graph( iri:string | Resource | Variable, patterns:Pattern | Pattern[] ): The pattern is applied within the context of the document specified.

  • .group( patterns:Pattern | Pattern[] ): Groups patterns into other patterns. This can be used to change the order of evaluation of the query, since SPARQL evaluates the inner-most group first.

  • .union( patterns:Pattern | Pattern[] ): One or more patterns may match. If more than one of the alternatives matches, all of them are united and returned as a single solution. To specify the list of patterns to be united, you can use a structure like .union( ... ).and( ... ).and( ... ).

  • .optional( patterns:Pattern | Pattern[] ): Regular queries reject solutions because part of the query pattern does not match. With .optional(), if the optional part does not match, it creates no bindings but does not eliminate the solution.

  • .minus( patterns:Pattern | Pattern[] ): Removes solutions related to another pattern. It evaluates it’s pattern and removes the results that match the previous results.

  • .service( resource:string | Resource | Variable, patterns:Pattern | Pattern[] ): Specifies that the pattern should be invoked on a remote SPARQL endpoint, that is, it gets data from another server. In case there is an error in the process, the query will stop and return the error.

  • .serviceSilent( resource:string | Resource | Variable, patterns:Pattern | Pattern[] ): Works the same as .service(), however if the remote SPARQL endpoint is not available because the SPARQL endpoint does not exist, it is down or it is not accessible, the query will return a solution sequence of one empty solution mapping instead of an error.

  • .filter( rawConstraint:string ): Restricts solutions to those for which the filter expression evaluates to TRUE. All other solutions will be discarted.

  • .bind( rawExpression:string, variable:string | Variable ): It assigns the rawExpression to the variable specified.

  • .values(...variables): Assigns data to the variables specified. You can use undefined to specify that a certain variable has no value.

Additionally, you can again use .select() or any of it’s variations in order to perform a sub-query. Subqueries are a way to embed SPARQL queries within other queries, normally to achieve results which cannot otherwise be achieved, such as limiting the number of results from some sub-expression within the query.

Example
this.carbonLDP.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( _ => {

        return [
            _.select("projects").where( [
                _.resource( "projects/" )
                .has( "ldp:contains", _.var( "projects" ) ),
                _.var( "projects" )
                .has( "ldp:admin", _.literal( "John Snow" ))
            ]), // returns all the projects in charge of John Snow
            _.var( "projects" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ]; // selects the name and start date of all projects managed by John Snow.
    } )
    .execute()
    .then( ( results ) => {
        console.log( results );
} );

Due to the bottom-up nature of SPARQL query evaluation, the subqueries are evaluated logically first, and the results are projected up to the outer query.

Property Paths

Carbon also supports property paths. With these, you can specify routes between two documents, which makes your queries more powerful. You can access properties from another document and use the information in the results of your query.

You can use the path() method to work with property paths. Inside this method, you can specify the path the query should take by using the following methods:

  • or(): An alternative path. (All possibilities are tried)
  • then(): Adds sequence path from the current one. (Indicates a connection)
  • negated(): Creates a negated path.
  • subPath(): Create a sub-path from a property or path. This helps to logically group paths.
  • inverse(): Create an inverse path from another one. Inverse paths change the order in which the path is analyzed. Instead of reading the query from left to right, it makes it so it is read from right to left.
  • oneOrNone(): Set the path to be matched one or zero times.
  • zeroOrMore(): Set the path to be matched zero or more times. It may connect the path multiple times and cycle the query, so it must be used carefully.
  • onceOrMore(): Set the path to be matched one or more times. It may connect the path multiple times and cycle the query, so it must be used carefully.
const queryResults = await this.carbon.documents.$sparql('employees/') // From the container of employees...
.select('employee', "name", "familyMemberName")   // ...get the name of the employee and its family members ...
.where(_ => [    // ...where...
    _.var('employee')    // ...employees...
        .has(EMPLOYEE_SCHEMA.name["@id"] ,_.var('name')), // ...have a name...
    _.var('employee')
        .has(_.path(EMPLOYEE_SCHEMA.familyMembers["@id"]).then(PERSON_SCHEMA.name["@id"]).or("rdfs:label"), _.var("familyMemberName")) // ... and have a family member with a name of type "rdfs:label" or the one specified under PERSON_SCHEMA.name (this creates a property path from employee - family member )
])
.limit(5) // Limit the results to 5
.offset(0) // Offset the results by 0 (Do not offset them)
.execute(); // Execute the query to the database

You can also pass a function to the path() method. The previous query is equivalent to this one:

const queryResults = await this.carbon.documents.$sparql('employees/') // From the container of employees...
.select('employee', "name", "familyMemberName")   // ...get the name of the employee and its family members ...
.where(_ => [    // ...where...
    _.var('employee')    // ...employees...
        .has(EMPLOYEE_SCHEMA.name["@id"] ,_.var('name')), // ...have a name...
    _.var('employee')
    .has(_.path( __ =>
            __.sequences(EMPLOYEE_SCHEMA.familyMembers["@id"], PERSON_SCHEMA.name["@id"]).or("rdfs:label")
        ), _.var("familyMemberName")) // ... and have a family member with a name of type "rdfs:label" or the one specified under PERSON_SCHEMA.name (this creates a property path from employee - family member )
])
.limit(5) // Limit the results to 5
.offset(0) // Offset the results by 0 (Do not offset them)
.execute(); // Execute the query to the database

Notice that in the second path(), to specify a sequence path you use sequence(). Similarly, to specify an alternative path, the method alternatives() method should be used instead.

Solution modifiers

This methods are optional and they let you modify the solutions returned:

  • .groupBy( rawCondition:string ). Group the data in order to calculate aggregated values for a solution
  • .having( rawCondition:string ). Filter grouped solution sets
  • .orderBy( rawCondition:string ). Establish the order of the a sequence of solutions
  • .limit( limit:string ). Restrict the number of solutions returned
  • .offset( offset:string ). Control where the solutions returned start from the overall set of them

Example

Considering the same case of retrieving the name and start date of every project, but with the solutions modifiers we’ll retrieve the last 10 projects that have been started.

let carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( _ => {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .orderBy( "DESC( ?projectStart )" )
    .limit( 10 )
    .execute()
    .then( ( results ) => {
        console.log( results );
    } );
import { PatternBuilder } from "sparqler/patterns";
import { SPARQLSelectResults } from "carbonldp/SPARQL";

let carbonldp:CarbonLDP;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( ( _:PatternBuilder ) => {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .orderBy( "DESC( ?projectStart )" )
    .limit( 10 )
    .execute()
    .then( ( results:SPARQLSelectResults ) => {
        console.log( results );
    } );
var carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( function( _ ) {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .orderBy( "DESC( ?projectStart )" )
    .limit( 10 )
    .execute()
    .then( function( results ) => {
        console.log( results );
    } );

We use the .orderBy() method to specify a descending order for the results, based on the project start date, and we use the .limit() method to limit the returned solutions to 10. Notice that it is not required to use a question mark with the variables declared with the _.var() helper. However, the solution modifiers like .orderBy() use RAW strings, so we have to use a question mark to specify the variable (e.g. ?projectStart.)

Query execution

Until now we’ve only been building the query and nothing more, but the important thing is to execute it and use the solutions returned.

For a SELECT query we have the following method:

Example

Following the previous examples, we’ll execute the query we have been building and then return an array of projects with the data obtained.

let carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( _ => {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .orderBy( "DESC( ?projectStart )" )
    .limit( 10 )
    .execute()
    .then( ( result ) => {
        return result
            .bindings
            .map( binding => ( {
                name: binding[ "projectName" ],
                startDate: binding[ "projectStart" ],
            } ) );
    } );
import { SPARQLSelectResults } from "carbonldp/SPARQL";
import { PatternBuilder } from "sparqler/patterns";

let carbonldp:CarbonLDP;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( ( _:PatternBuilder ) => {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .orderBy( "DESC( ?projectStart )" )
    .limit( 10 )
    .execute()
    .then( ( result:SPARQLSelectResults ) => {
        return result
            .bindings
            .map( binding => ( {
                name: binding[ "projectName" ],
                startDate: binding[ "projectStart" ],
            } ) );
    } );
var carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "projects/" )
    .prefix( "ldp", "http://www.w3.org/ns/ldp#" )
    .select( "projectName", "projectStart" )
    .where( function( _ ) {
        return [
            _.resource( "projects/" )
                .has( "ldp:contains", _.var( "everyProject" ) ),
            _.var( "everyProject" )
                .has( "name", _.var( "projectName" ) )
                .and( "startDate", _.var( "projectStart" ) )
        ];
    } )
    .orderBy( "DESC( ?projectStart )" )
    .limit( 10 )
    .execute()
    .then( function( result ) {
        return result
            .bindings
            .map( function( binding ) {
                return {
                    name: binding[ "projectName" ],
                    startDate: binding[ "projectStart" ],
                }
            } );
    } );

The result object contains a bindings property with an array containing the solutions of the query. Every element in this array is an object that has the variable names as keys and each variable’s bound value.

Query configuration

With the SPARQLER integration, every query has access to the following default information:

  • Prefixes. Every prefix in the global schema
  • Vocabulary. The platform instance vocabulary to resolve property names, as in the Object Schema
  • Base. The URI where your platform instance lives, against which relative URIs will be resolved.

To configure the builder to your own preferences you can use the following methods:

  • vocab( uri:string ): Set or replace the existing vocabulary
  • base( uri:string ): Replace the base URI
  • prefix( name:string, uri:string ): Add or replace existing prefixes in the SPARQLER

Example

let carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "resource-end-point/" )
    // Sets a well defined vocabulary
    .vocab( "https://schema.org/" )

    // Sets the base to the document end point
    .base( "resource-end-point/" )

    // Adds new prefixes that may be used in the document
    .prefix( "bib", "https://bib.schema.org/" )
    .prefix( "auto", "https://auto.schema.org/" );
let carbonldp:CarbonLDP;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "resource-end-point/" )
    // Sets a well defined vocabulary
    .vocab( "https://schema.org/" )

    // Sets the base to the document end point
    .base( "resource-end-point/" )

    // Adds new prefixes that may be used in the document
    .prefix( "bib", "https://bib.schema.org/" )
    .prefix( "auto", "https://auto.schema.org/" );
var carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$sparql( "resource-end-point/" )
    // Sets a well defined vocabulary
    .vocab( "https://schema.org/" )

    // Sets the base to the document end point
    .base( "resource-end-point/" )

    // Adds new prefixes that may be used in the document
    .prefix( "bib", "https://bib.schema.org/" )
    .prefix( "auto", "https://auto.schema.org/" );

As an alternative to the way of building queries with the SPARQL Query Builder (as we’ve shown so far), the SDK also supports the use of standard SPARQL queries passed as strings. You might prefer this approach when if you are comfortable writing standard SPARQL queries or in order to leverage features that are not yet available in the SPARQL Query Builder.

Standard SPARQL queries can be written and tested using the SPARQL Client in the Carbon LDP Workbench. They can then be copied and pasted directly into JavaScript strings as-is. A notable difference is that relative property names cannot be used as they can in the SPARQL Query Builder, so standard SPARQL queries might be more verbose with fully qualified URIs in some cases.

The methods to execute a standard SPARQL query (given as a string), are also called from the Documents endpoint.

SELECT Queries

This method is the equivalent to the .execute() method in a SELECT query with the Query Builder.

let carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$executeSELECTQuery( "projects/", `
    BASE <http://localhost:8083/>
    PREFIX ldp: <http://www.w3.org/ns/ldp#>
    SELECT ?projectName ?projectStart
    WHERE {
        <projects/> ldp:contains ?everyProject .
        ?everyProject <vocabularies/main/#name> ?projectName ;
                      <vocabularies/main/#startDate> ?projectStart
    }
    ORDER BY DESC( ?projectStart )
    LIMIT 10
` )
.then( ( result ) => {
    return result
        .bindings
        .map( binding => ( {
                name: binding[ "projectName" ],
                startDate: binding[ "projectStart" ],
            } )
        );
} );
import { SPARQLSelectResults } from "carbonldp/SPARQL";

let carbonldp:CarbonLDP;

// ... initialize your CarbonLDP object

carbonldp.documents.$executeSELECTQuery( "projects/", `
    BASE <http://localhost:8083/>
    PREFIX ldp: <http://www.w3.org/ns/ldp#>
    SELECT ?projectName ?projectStart
    WHERE {
        <projects/> ldp:contains ?everyProject .
        ?everyProject <vocabularies/main/#name> ?projectName ;
                      <vocabularies/main/#startDate> ?projectStart
    }
    ORDER BY DESC( ?projectStart )
    LIMIT 10
` )
.then( ( result:SPARQLSelectResults ) => {
    return result
        .bindings
        .map( binding => ( {
                name: binding[ "projectName" ],
                startDate: binding[ "projectStart" ],
            } )
        );
} );
var carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$executeSELECTQuery( "projects/", "" +
    "BASE <http://localhost:8083/>" +
    "PREFIX ldp: <http://www.w3.org/ns/ldp#>" +
    "SELECT ?projectName ?projectStart" +
    "WHERE {" +
    "   <projects/> ldp:contains ?everyProject ." +
    "   ?everyProject <vocabularies/main/#name> ?projectName ;" +
    "                 <vocabularies/main/#startDate> ?projectStart" +
    "}" +
    "ORDER BY DESC( ?projectStart )" +
    "LIMIT 10"
)
.then( function( result ) {
    return result
        .bindings
        .map( function( binding ) {
            return {
                name: binding[ "projectName" ],
                startDate: binding[ "projectStart" ],
            };
        } );
} );

ASK Queries

A standard SPARQL ASK query can be given as string and executed with the following:

This option returns a simple response with only the resulting boolean of the ASK query (e.g. true or false).

let carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$executeASKQuery( "projects/project-01/", `
    BASE        <http://localhost:8083/>
    ASK {
        <projects/project-01/> <vocabularies/main/#name> "Project X" ;
                               <vocabularies/main/#startDate> "2017/02/19"
    }
` )
    .then( ( result ) => {
        // result will be `true`
    } );
let carbonldp:CarbonLDP;

// ... initialize your CarbonLDP object

carbonldp.documents.$executeASKQuery( "projects/project-01/", `
    BASE        <http://localhost:8083/>
    ASK {
        <projects/project-01/> <vocabularies/main/#name> "Project X" ;
                               <vocabularies/main/#startDate> "2017/02/19"
    }
` )
    .then( ( result:boolean ) => {
        // result will be `true`
    } );
var carbonldp;

// ... initialize your CarbonLDP object

carbonldp.documents.$executeASKQuery( "projects/project-01/", "" +
    "BASE        <http://localhost:8083/>" +
    "ASK {" +
    "    <projects/project-01/> <vocabularies/main/#name> \"Project X\" ;" +
    "                           <vocabularies/main/#startDate> \"2017/02/19\"" +
    "}" +
)
    .then( function( result ) {
        // result will be `true`
    } );

Raw queries

Finally, we understand that you may want to use SPARQL methods that are not available through the documents endpoint, or you may want to access information contained in external domains. In order to do this, you can use the following methods of
the SPARQLService:

  • executeRawSelectQuery( documentURI:string, rawQuery: string )
  • executeRawAskQuery( documentURI:string, rawQuery: string )
  • executeRawConstructQuery( documentURI:string, rawQuery: string )
  • executeRawDescribeQuery( documentURI:string, rawQuery: string )

Along with the regular Response, the SELECT and ASK methods will return a SPARQLRawResults object, while the CONSTRUCT and DESCRIBE will return an un-parsed String, which you can then use at your convenience.

Conclusion

In this guide, we’ve demonstrated two alternative ways to query with SPARQL using the SDK:

  • Using the SPARQL Query Builder (a.k.a. SPARQLER) – a fluent chain of methods assembled in a dot-notation to build up a query.
  • Using SPARQL Services – methods that accept a standard SPARQL query string passed in a parameter to the method.

We also provided an overview, with code examples, for the different query forms SELECT, ASK and UPDATE.

Want to know more?

Now that you understand how to query with SPARQL using the SDK, you may want to learn more about the SPARQL language. We recommend the following references:

RDF Icon carbonldp – for general discussions related to using Carbon LDP (Platform, REST API, product documentation)

RDF Icon SPARQL 1.1 Overview – Introduction from the W3C.

RDF Icon SPARQL 1.1 Query Language – Specification from the W3C.

RDF Icon Learning SPARQL – Book about Querying and Updating with SPARQL 1.1, by Bob DuCharme, O’REILLY®.