Building SPARQL
SPARQL is the standard query language for the Semantic Web and can be used to query large volumes of RDF data. SPARQL Query Language Specification defines the syntax and semantics of the language and explains SPARQL query buildling with numerous examples. SPARQL standard is drafted and maintained by W3C.
dotNetRDF facilitates SPARQL construction with a set of APIs under VDS.RDF.Query.Builder
namespace. We'll look at some of the common queries patterns you can construct using dotNetRDF.
Hello World
Constructing a simple "Hello World" SPARQL. This query fetches all users whose last name is "John Smith"
SELECT ?x
WHERE { ?x <http://www.w3.org/2001/vcard-rdf/3.0#FN> "John Smith" }
using System;
using VDS.RDF.Query.Builder;
static void HelloWorld()
{
string x = "x";
var queryBuilder =
QueryBuilder
.Select(new string[] { x })
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject(x)
.PredicateUri(new Uri("http://www.w3.org/2001/vcard-rdf/3.0#FN"))
.Object("John Smith");
});
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
PREFIX
with multiple triples
The query fetches given names for the family name "Smith".
PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
SELECT ?givenName
WHERE
{
?y vcard:Family "Smith" .
?y vcard:Given ?givenName .
}
using System;
using VDS.RDF;
using VDS.RDF.Query;
using VDS.RDF.Query.Builder;
static void WithPrefix()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("vcard", new Uri("http://www.w3.org/2001/vcard-rdf/3.0#"));
string y = "y";
var givenName = new SparqlVariable("givenName");
var queryBuilder =
QueryBuilder
.Select(new SparqlVariable[] { givenName })
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject(y)
.PredicateUri("vcard:Family")
.Object("Smith");
triplePatternBuilder
.Subject(y)
.PredicateUri("vcard:Given")
.Object(givenName);
});
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
Numeric FILTER
This query filters resources above 24 years of age.
PREFIX info: < http://somewhere/peopleInfo#>
SELECT ?resource
WHERE
{
?resource info:age ?age .
FILTER(?age >= 24)
}
using System;
using VDS.RDF;
using VDS.RDF.Query;
using VDS.RDF.Query.Builder;
static void WithNumericFilter()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("info", new Uri("http://somewhere/peopleInfo#"));
string resource = "resource";
string age = "age";
var queryBuilder =
QueryBuilder
.Select(new string[] { resource })
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject(resource)
.PredicateUri($"info:{age}")
.Object(age);
})
.Filter((builder) => builder.Variable(age) > 24);
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
Regex FILTER
This query filters given names based on a case-insensitive regex comparison.
PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
SELECT ?g
WHERE
{
?y vcard:Given ?g .
FILTER regex(?g, "sarah", "i")
}
using System;
using VDS.RDF;
using VDS.RDF.Query;
using VDS.RDF.Query.Builder;
static void WithRegexFilter()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("vcard", new Uri("http://www.w3.org/2001/vcard-rdf/3.0#"));
var givenName = new SparqlVariable("givenName");
var queryBuilder =
QueryBuilder
.Select(new SparqlVariable[] { givenName })
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject("y")
.PredicateUri("vcard:Given")
.Object(givenName);
})
.Filter((builder) => builder.Regex(builder.Variable("givenName"), "sarah", "i"));
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
OPTIONAL
clause with FILTER
This query fetches name and optional age above 42.
PREFIX info: <http://somewhere/peopleInfo#>
PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
SELECT ?name ?age
WHERE
{
?person vcard:FN ?name .
OPTIONAL { ?person info:age ?age . FILTER ( ?age > 42 ) }
}
static void WithOptionalAndFilter()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("info", new Uri("http://somewhere/peopleInfo#"));
prefixes.AddNamespace("vcard", new Uri("http://www.w3.org/2001/vcard-rdf/3.0#"));
string name = "name";
string age = "age";
string person = "person";
var queryBuilder =
QueryBuilder
.Select(new string[] { name, age })
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject(person)
.PredicateUri("vcard:FN")
.Object(name);
})
.Optional(
(optionalBuilder) =>
{
optionalBuilder.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject(person)
.PredicateUri($"info:{age}")
.Object(age);
});
optionalBuilder.Filter((b) => b.Variable(age) > 42);
});
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
UNION
This query unions two triple patterns.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
SELECT ?name
WHERE
{
{ [] foaf:name ?name } UNION { [] vcard:FN ?name }
}
public static void WithUnion()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("foaf", new Uri("http://xmlns.com/foaf/0.1/"));
prefixes.AddNamespace("vcard", new Uri("http://www.w3.org/2001/vcard-rdf/3.0#"));
string name = "name";
var queryBuilder =
QueryBuilder
.Select(new string[] { name })
.GetQueryBuilder();
queryBuilder
.Union(
(unionBuilder) =>
{
unionBuilder.Where(
(tripleBuilder) =>
{
tripleBuilder
.Subject<IBlankNode>("abc")
.PredicateUri($"foaf:{name}")
.Object(name);
});
},
(unionBuilder) =>
{
unionBuilder.Where(
c =>
{
c
.Subject<IBlankNode>("abc")
.PredicateUri("vcard:FN")
.Object(name);
});
});
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
ORDER BY
This query orders by name.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name }
ORDER BY ?name
static void WithOrderBy()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("foaf", new Uri("http://xmlns.com/foaf/0.1/"));
string name = "name";
var queryBuilder =
QueryBuilder
.Select(new string[] { name })
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject("x")
.PredicateUri($"foaf:{name}")
.Object(name);
})
.OrderBy(name);
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
DISTINCT
This query enforces distinctness on names.
PREFIX foaf: < http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?name WHERE { ?x foaf:name? name }
static void WithDistinct()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("foaf", new Uri("http://xmlns.com/foaf/0.1/"));
string name = "name";
var queryBuilder =
QueryBuilder
.Select(new string[] { name })
.Distinct()
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject("x")
.PredicateUri($"foaf:{name}")
.Object(name);
});
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
LIMIT
This query limits the result set to 20.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name }
LIMIT 20
static void WithLimit()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("foaf", new Uri("http://xmlns.com/foaf/0.1/"));
string name = "name";
var queryBuilder =
QueryBuilder
.Select(new string[] { name })
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject("x")
.PredicateUri($"foaf:{name}")
.Object(name);
})
.Limit(20);
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
BIND
This query creates a computed column with an alias using BIND
.
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX ns: <http://example.org/ns#>
SELECT ?price
WHERE
{ ?x ns:price ?p .
?x ns:discount ?discount
BIND (?p*(1-?discount) AS ?price)
}
static void WithBind()
{
var prefixes = new NamespaceMapper(true);
prefixes.AddNamespace("dc", new Uri("http://purl.org/dc/elements/1.1/"));
prefixes.AddNamespace("ns", new Uri("http://example.org/ns#"));
string p = "p";
string x = "x";
string discount = "discount";
string price = "price";
var queryBuilder =
QueryBuilder
.Select(price)
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject(x)
.PredicateUri($"ns:{price}")
.Object(p);
triplePatternBuilder
.Subject(x)
.PredicateUri($"ns:{discount}")
.Object(discount);
})
.Bind((builder) => builder.Variable(p) * (1 - builder.Variable(discount)))
.As(price);
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}
Term Constraints
This query demonstrates enforcing type constraints on terms.
PREFIX info: < http://somewhere/peopleInfo#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?resource
WHERE
{
?resource info:bornafter ?bornafter .
FILTER(?bornafter >= "1970-01-01T00:00:00.000000"^^xsd:dateTime)
}
static void WithTermConstraints()
{
var prefixes = new NamespaceMapper(false);
prefixes.AddNamespace("info", new Uri("http://somewhere/peopleInfo#"));
string resource = "resource";
string bornafter = "bornafter";
var queryBuilder =
QueryBuilder
.Select(new string[] { resource })
.Where(
(triplePatternBuilder) =>
{
triplePatternBuilder
.Subject(resource)
.PredicateUri($"info:{bornafter}")
.Object(bornafter);
})
.Filter((builder) => builder.Variable(bornafter) >= builder.Constant(new DateTime(1970, 1, 1)));
queryBuilder.Prefixes = prefixes;
Console.WriteLine(queryBuilder.BuildQuery().ToString());
}