Updating in a JavaScript app


On this page

    Comunica SPARQL (@comunica/actor-init-sparql) allow you to initiate queries to update data in a certain store. In this guide, we will build upon the guide on querying in a JavaScript app, and show how you can not only read, but also update data.

    1. Creating a new query engine and store

    The easiest way to create an engine and store is as follows:

    const newEngine = require('@comunica/actor-init-sparql').newEngine;
    const N3 = require('n3');
    
    const myEngine = newEngine();
    
    const store = new N3.Store();
    

    We make use of the Store from N3.js for these examples.

    2. Executing INSERT DATA queries

    Once you engine has been created, you can use it to execute any SPARQL Update query, such as a INSERT DATA query:

    // Initiate the update
    const result = await myEngine.query(`
      PREFIX dc: <http://purl.org/dc/elements/1.1/>
      INSERT DATA
      { 
        <http://example/book1> dc:title "A new book" ;
                               dc:creator "A.N.Other" .
      }`, {
      sources: [ store ],
    });
    
    // Wait for the update to complete
    await result.updateResult;
    
    // Prints '2' => the store is updated
    console.log(store.size);
    

    When you obtain the result of the query method, this means that your query has been initiated. In order to wait until the update operation has been completed, you need to await the updateResult.

    3. Executing DELETE/INSERT WHERE queries

    DELETE/INSERT WHERE queries allow you to delete and insert new quads, based on quads that are already available:

    // Insert initial data
    await (await myEngine.query(`
      PREFIX foaf: <http://xmlns.com/foaf/0.1/>
      INSERT DATA
      { 
        <http://example/president25> foaf:givenName "Bill" .
        <http://example/president25> foaf:familyName "McKinley" .
        <http://example/president27> foaf:givenName "Bill" .
        <http://example/president27> foaf:familyName "Taft" .
        <http://example/president42> foaf:givenName "Bill" .
        <http://example/president42> foaf:familyName "Clinton" .
      }`, {
      sources: [ store ],
    })).updateResult;
    
    // Rename all occurrences of "Bill" to "William"
    await (await myEngine.query(`
      PREFIX foaf:  <http://xmlns.com/foaf/0.1/>
      DELETE { ?person foaf:givenName 'Bill' }
      INSERT { ?person foaf:givenName 'William' }
      WHERE
      {
        ?person foaf:givenName 'Bill' 
      }`, {
      sources: [ store ],
    })).updateResult;
    
    For more information on the types of update queries that are possible, please refer to the SPARQL Update specification.

    4. Configure a custom destination

    By default, update queries will modify data within the given source. In some cases, you may want to direct changes to another place. For example, if you have multiple sources, but you want to direct all changes to a single source.

    This can be done by passing a destination into the query context:

    // Insert friends based on common friends from Ruben's
    await (await myEngine.query(`
      PREFIX foaf:  <http://xmlns.com/foaf/0.1/>
      INSERT
      {
        <http://example/person> foaf:knows ?friend
      }
      WHERE
      {
        <https://www.rubensworks.net/#me> foaf:knows ?friend .
        <https://ruben.verborgh.org/profile/#me> foaf:knows ?friend . 
      }`, {
      sources: [
        'https://www.rubensworks.net/',
        'https://ruben.verborgh.org/profile/',
      ],
      destination: store,
    })).updateResult;
    
    Instead of passing an RDF/JS store as destination, you may also pass other types of destinations.