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?
-
Designed for querying a single data store
-
Designed to query through dedicated endpoints
-
There are efforts to federate SPARQL queries, but you usually need to know the endpoints ahead of time
-
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,838