Ruben Verborgh, Ghent University – imec
These slides are an abridged version of my Web Fundamentals course.
Ruben Verborgh
Surely there must be something easier.
I used to like math, until
the numbers were being
outnumbered by letters.And then the letters
Dieter DP
started having letters.
💰 🍎🍏 📦
I bought a crate of apples for £20
and just sold 6 apples for £5 each.
What is my profit?
10 = 5 ⋅ 6 − 20
This solves buying a crate of apples for £20
and selling 6 apples for £5 each.
f(x) = 5 x − 20
This solves selling an arbitrary number of apples,
and even half an apple or negative apples due to loss.
f(x) = a x + b
This solves selling arbitrary numbers of anything,
and whole other kinds of problems.
In order to simplify,
Gaston Julia (as quoted by Benoît Mandelbrot)
one must complexify,
i.e., see simple things
in the complex plane.
What happened to good old natural numbers?
People think RDF is a pain
because it is complicated.
The truth is even worse.RDF is painfully simplistic,
Dan Brickley & Libby Miller
but it allows you to work with real-world data
and problems that are horribly complicated.
The Semantic Web isn’t just about putting data on the Web. It is about making links, so that a person or machine can explore the Web of Data.
With Linked Data, when you have some of it,
Tim Berners-Lee
you can find other, related, data.
NULL
values are typically undesired.
<http://dbpedia.org/resource/Tim_Berners-Lee> <http://xmlns.com/foaf/0.1/knows> <http://dbpedia.org/resource/Ted_Nelson>.
<http://dbpedia.org/resource/Tim_Berners-Lee> <http://xmlns.com/foaf/0.1/givenName> "Tim"@en.
<http://dbpedia.org/resource/Tim_Berners-Lee> <http://dbpedia.org/ontology/birthDate> "1955-06-08"^^<http://www.w3.org/2001/XMLSchema#date>.
PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
dbr:Tim_Berners-Lee a foaf:Person;
foaf:knows dbr:Ted_Nelson,
dbr:Wendy_Hall.
# Triples in the default graph look like N-Triples
<urn:ex:s1> <urn:ex:p1> <urn:ex:o1>.
<urn:ex:s1> <urn:ex:p2> "abc".
# Triples in named graphs have a fourth element
<urn:ex:s2> <urn:ex:p1> <urn:ex:o2> <urn:ex:GraphA>.
<urn:ex:s2> <urn:ex:p2> "xyz" <urn:ex:GraphB>.
# Triples in the default graph look like Turtle
dbr:Tim_Berners-Lee foaf:knows dbr:Ted_Nelson.
# Named graphs are indicated by a graph statement
<http://example.org/graphs/Fiction> {
dbr:Clark_Kent a foaf:Person;
foaf:nick "Superman"@en.
}
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:schema="http://schema.org/">
<rdf:Description rdf:about="http://dbpedia.org/resource/Ted_Nelson">
<schema:givenName>Ted</schema:givenName>
</rdf:Description>
<rdf:Description rdf:about="http://dbpedia.org/resource/Tim_Berners-Lee">
<schema:givenName>Tim</schema:givenName>
<schema:knows rdf:resource="http://dbpedia.org/resource/Ted_Nelson"/>
</rdf:Description>
</rdf:RDF>
@context
or an HTTP Link
header.
@id
keyword
enables making subjects explicit.
{
"name": "Jane Doe",
"type": "Person",
"telephone": "(425) 123-4567",
"url": "http://www.janedoe.com/"
}
{
"@context": "http://schema.org/",
"name": "Jane Doe",
"@type": "Person",
"telephone": "(425) 123-4567",
"url": "http://www.janedoe.com/"
}
application/json
with HTTP Link
contextapplication/ld+json
with @context
key{
"@context": "http://schema.org/",
"@graph": [{
"id": "http://dbpedia.org/resource/Ted_Nelson",
"http://schema.org/givenName": "Ted"
}, {
"id": "http://dbpedia.org/resource/Tim_Berners-Lee",
"http://schema.org/givenName": "Tim",
"foaf:knows": { "id": "http://dbpedia.org/resource/Ted_Nelson" }
}]
}
{
"@context": "http://schema.org/",
"id": "http://dbpedia.org/resource/Tim_Berners-Lee",
"givenName": "Tim",
"knows": [{
"id": "http://dbpedia.org/resource/Ted_Nelson",
"givenName": "Ted"
}]
}
{
"@context": "http://schema.org/",
"id": "http://dbpedia.org/resource/Tim_Berners-Lee",
"givenName": "Tim",
"knows": [{
"id": "http://dbpedia.org/resource/Ted_Nelson",
"givenName": "Ted"
}]
}
PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX schema: <http://schema.org>
dbr:Ted_Nelson schema:givenName "Ted".
dbr:Tim_Berners-Lee schema:givenName "Tim";
schema:knows dbr:Ted_Nelson.
// Retrieve a JSON-LD document
const response = await fetch('https://pod.example/contacts',
{ 'Accept': 'application/ld+json' });
const contacts = await response.json();
// Print the name of the first contact
console.log(contacts.knows[0].givenName);
<div vocab="http://xmlns.com/foaf/0.1/" typeof="Person">
<p>
<span property="name">Alice Birpemswick</span>,
(<a property="mbox" href="mailto:alice@example.com">alice@example.com</a>)
</p>
<ul>
<li property="knows" typeof="Person">
<a property="homepage" href="https://example.com/bob/">Bob</a>
</li>
<li property="knows" typeof="Person" resource="https://example.com/people/#eve">
<span property="name">Eve</span>
</li>
</ul>
</div>
[] a foaf:Person;
foaf:name "Alice Birpemswick".
foaf:mbox <mailto:alice@example.com>;
foaf:knows [ a foaf:Person;
foaf:homepage <https://example.com/bob/> ],
<https://example.com/people/#eve>;
<https://example.com/people/#eve> a foaf:Person;
foaf:name "Eve".
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "#ruben-likes-stirrups",
"type": "Like",
"actor": "https://ruben.verborgh.org/profile/#me",
"object": "https://www.stirrupshotel.co.uk/#this",
"published": "2022-07-25T08:00:00Z"
}
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "#ruben-likes-stirrups",
"type": "Like",
"actor": "https://ruben.verborgh.org/profile/#me",
"object": "https://www.stirrupshotel.co.uk/#this",
"published": "2022-07-25T08:00:00Z"
}
{
"@context": "https://www.w3.org/ns/activitystreams",
"@graph": [{
"type": "Like",
"actor": "https://ruben.verborgh.org/profile/#me",
"object": "https://www.stirrupshotel.co.uk/#this",
"published": "2022-07-25T08:00:00Z"
},{
"type": "Like",
"actor": "https://virginiabalseiro.com/#me",
"object": "https://www.stirrupshotel.co.uk/#this",
"published": "2022-07-25T08:05:00Z"
}]
}
rdfs:label
rdfs:comment
rdfs:seeAlso
rdf:type
rdfs:Resource
rdfs:Class
rdfs:Literal
rdf:Property
rdfs:subClassOf
rdfs:domain
rdfs:range
rdfs:subPropertyOf
rdfs:label
is a property that givesPREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
foaf:knows rdfs:label "knows"@en, "kent"@nl, "connaît"@fr.
rdfs:label rdfs:label "label"@en.
rdf:type
is a property stating that<#me> rdf:type foaf:Person.
rdf:type rdf:type rdf:Property.
# Turtle and TriG allow a in predicate position
<#me> a foaf:Person.
rdf:type a rdf:Property.
rdfs:subClassOf
is a property stating<#Developer> a rdfs:Class.
foaf:Person a rdfs:Class.
rdfs:Resource a rdfs:Class.
rdfs:Class a rdfs:Class.
<#Developer> rdfs:subClassOf foaf:Person.
foaf:Person rdfs:subClassOf foaf:Agent.
foaf:Person rdfs:subClassOf rdfs:Resource.
rdfs:Class rdfs:subClassOf rdfs:Resource.
rdfs:domain
is a property that statesfoaf:img rdfs:domain foaf:Person.
foaf:img rdfs:domain foaf:Resource.
rdf:type rdfs:domain rdfs:Resource.
rdfs:domain rdfs:domain rdf:Property.
rdfs:range
is a property that statesfoaf:img rdfs:range foaf:Image.
foaf:img rdfs:range foaf:Resource.
rdf:type rdfs:range rdfs:Class.
rdf:type rdfs:range rdfs:Resource.
rdfs:range rdfs:range rdfs:Class.
rdfs:subPropertyOf
is a property stating<#hasFriend> rdfs:subPropertyOf foaf:knows.
rdfs:range rdfs:subPropertyOf rdfs:seeAlso.
rdfs:domain rdfs:subPropertyOf rdfs:seeAlso.
For example, the presence of
<#Tim> foaf:knows <#Wendy>.
foaf:knows rdfs:domain foaf:Person.
will result in an extra triple
<#Tim> a foaf:Person.
To get started, try reading these vocabularies:
owl:sameAs
owl:differentFrom
owl:ObjectProperty
owl:inverseOf
owl:FunctionalProperty
owl:intersectionOf
owl:Restriction
owl:DataTypeProperty
.
foaf:givenName a owl:DataTypeProperty.
owl:ObjectProperty
.
foaf:knows a owl:ObjectProperty.
owl:inverseOf
anotherex:TimBL foaf:made dbr:World_Wide_Web.
dbr:World_Wide_Web foaf:maker ex:TimBL.
foaf:made owl:inverseOf foaf:maker
owl:inverseOf
allows connecting such properties.owl:FunctionalProperty
.
ex:Julia ex:hasSpouse ex:Cathy.
ex:hasSpouse a owl:FunctionalProperty.
ex:Julia ex:hasSpouse ex:Cathy.
ex:Julia ex:hasSpouse ex:John.
ex:hasSpouse a owl:FunctionalProperty.
Perhaps counterintuitively, the conclusion is:
ex:Cathy owl:sameAs ex:John.
To arrive at a contradiction, explicitly define inequality:
ex:Cathy owl:differentFrom ex:John.
ex:Single owl:equivalentClass [ a owl:Class;
owl:intersectionOf (foaf:Person, [
a owl:Class, owl:Restriction;
owl:onProperty ex:hasPartner;
owl:maxCardinality 0
])
].
For example, the presence of
<#me> ex:hasSpouse <#SignificantOther>.
together with the earlier class restrictions
ensures the following triple cannot be true:
<#me> a ex:Single.
?name
{ ?x a foaf:Person. }
{ … } => { … }.
docker/eye/
folder./build
./reason test.n3
./reason *.n3 *.ttl --query find-people.n3
./reason *.n3 *.ttl --query find-places.n3
./reason *.n3 *.ttl --query find-organizations.n3
# List 10 people and their names
{
person(first:10) {
name
}
}
# List 10 people and their names
{
users(first:10) {
fullName
}
}
# List 10 people and their names
{
friends(first:10) {
displayName
}
}
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
# List 10 people and their names
SELECT * {
?person a dbo:Person;
rdfs:label ?name.
}
LIMIT 10
PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?name ?person WHERE {
?person a dbo:Artist.
?person foaf:name ?name.
?person dbo:influencedBy dbr:Pablo_Picasso.
}
The dataset must contain these triples
after substituting the variables:
?person a dbo:Artist.
?person foaf:name ?name.
?person dbo:influencedBy dbr:Pablo_Picasso.
SELECT
queryCONSTRUCT
queryASK
query returns a boolean statingDESCRIBE
query returns (non-specified)null
for ?spouse
ex:Single
?
docker/sparql/
,
then build (./build
)./start *.ttl
)
your SPARQL endpoint
http://localhost:3000/dataset/sparql?query={SPARQL}
curl http://localhost:3000/dataset/sparql -G --data-urlencode query@query.sparql