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:labelrdfs:commentrdfs:seeAlsordf:typerdfs:Resourcerdfs:Classrdfs:Literalrdf:Propertyrdfs:subClassOfrdfs:domainrdfs:rangerdfs:subPropertyOfrdfs: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:sameAsowl:differentFromowl:ObjectPropertyowl:inverseOfowl:FunctionalPropertyowl:intersectionOfowl:Restrictionowl: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:makerowl: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 ?spouseex: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