twinql,

the query language

Motivation

1. Decentralized knowledge graphs are great sources of data, but so is aggregated data. There is a case to be made for both.

 

 

  • Aggregated     -- makes life easier for developers
  • Decentralized -- users prefer control

more

Motivation

2. Access to data requires authentication (often across different domains). The solution usually puts the burden on the user.

Motivation

3. Documents may contain data that is not useful (i.e. how do I just get the name and picture?).

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

<>
    a <http://xmlns.com/foaf/0.1/PersonalProfileDocument> ;
    <http://xmlns.com/foaf/0.1/primaryTopic> <#me> .

<#me>
    a <http://xmlns.com/foaf/0.1/Person> ;
    <http://www.w3.org/ns/auth/cert#key> <#keyone> ;
    <http://www.w3.org/ns/pim/space#preferencesFile> <Preferences/prefs> ;
    <http://www.w3.org/ns/pim/space#storage> <.> ;
    <http://www.w3.org/ns/solid/terms#inbox> <inbox/> ;
    <http://www.w3.org/ns/solid/terms#privateTypeIndex> <privIndex.ttl> ;
    <http://www.w3.org/ns/solid/terms#publicTypeIndex> <publicTypeIndex.ttl> ;
    <http://xmlns.com/foaf/0.1/img> <avatar.jpg> ;
    <http://xmlns.com/foaf/0.1/mbox> <mailto:andrei@fcns.eu>, <mailto:andrei@w3.org> ;
    <http://xmlns.com/foaf/0.1/name> "Andrei Vlad Sambra" ;
    <http://xmlns.com/foaf/0.1/nick> "Deiu" ;
........

Motivation

4. Fetching from multiple locations can go wrong on different fronts

  • CORS
  • authentication
  • availability
    • timeouts
    • dead links

Why not use SPARQL?

  1. Designed for querying a single data store

  2. Designed to query through dedicated endpoints

  3. There are efforts to federate SPARQL queries, but you usually need to know the endpoints ahead of time

  4. Link-following SPARQL has been proposed as an improvement to SPARQL, but it hasn't been fully implemented/supported and the response would still be flat (apps require additional logic to map the data to the UI)

twinql

Why twinql?

1. Developers want tools that match how they think about UI. For this reason, twinql allows you to specify the shape of the data to match the UI.

@prefix foaf http://xmlns.com/foaf/0.1/

https://bob.me/profile#me {
  foaf.name
  foaf.knows {
    foaf.name
    foaf.image
  }
}
{
  "@context": {
    "foaf": "http://xmlns.com/foaf/0.1/"
  },
  "@id": "https://bob.me/profile#me",
  "foaf:name": [
    "Bob"
  ],
  "foaf:knows": [
    {
      "@id": "https://alice.me/card#me",
      "foaf:name": [
        "Alice"
      ],
      "foaf:img": [
        "https://alice.me/avatar.jpg"
      ]
.....

more

2. As opposed to SPARQL, data comes from individual requests to the resources' own URIs. Yes, this means you can even query over a bunch of static documents! Take Tim Berner-Lee's static FOAF document for example:

@prefix rdf http://www.w3.org/1999/02/22-rdf-syntax-ns#
@prefix dc http://purl.org/dc/elements/1.1/

https://www.w3.org/People/Berners-Lee/card {
  dc.title
  rdf.type
}
{
  "@context": {
    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    "dc": "http://purl.org/dc/elements/1.1/"
  },
  "@id": "https://www.w3.org/People/Berners-Lee/card",
  "dc:title": [
    "Tim Berners-Lee's FOAF file"
  ],
  "rdf:type": [
    "http://xmlns.com/foaf/0.1/PersonalProfileDocument"
  ]
}

Results in:

Why twinql?

2. Cross-domain auth is hard. Don't overwhelm the user with too much UI. Delegate!

Any auth

Delegation*

* WebID-TLS delegation

Device

Server (with agent)

The Web

Why twinql?

3. Asking for data right now is incredibly imperative (hundreds of lines of code).

 

Given a data model three levels deep and with a branch factor of B:

  1. Ask for the original thing

        Handle error

  2. Ask for next things

        Handle each error

  3. For each of those ask for next things

        Handle each error

There are B * D network requests/errors to deal with at the HTTP level alone.

Why twinql?

Example of imperative programming using Solid-Client

(no room to even show the result)

// Display name and picture for a person

var webid = 'https://bob.me/profile#me'
solid.web.get(webid).then(function(response) {
    var graph = response.parsedGraph()
    var subject = $rdf.sym(response.url)
    // get name
    var obj = graph.any(subject, vocab.foaf('name'))
    if (obj) {
        name = obj.value
    }
    // get picture
    obj = graph.any(subject, vocab.foaf('img'))
    if (obj) {
        pic = obj.value
    }

    // Do something in the UI with the name and picture

}).catch(function(err) {
    // do something with the HTTP error
    console.log(err)
})

Why twinql?

Same data requested, this time using twinql

// Display name and picture for a person

@prefix foaf http://xmlns.com/foaf/0.1/

https://bob.me/profile#me {
  foaf.name
  foaf.img
}
{
  "@context": {
    "foaf": "http://xmlns.com/foaf/0.1/"
  },
  "@id": "https://bob.me/profile#me",
  "foaf:img": [
    "https://bob.me/avatar.jpg"
  ],
  "foaf:name": [
    "Bob"
  ]
}

Result (in JSON-LD)

Why twinql?

Demos!

What's next?

Roadmap

  • filtering

  • ordering

  • pagination

  • property binding/reuse

  • mutations (write/update operations)

  • performance

Thank you!

Authors:

Dan Friedman

Andrei Sambra

twinql

By Andrei

twinql

  • 2,677