Skip to content

FILTER ​

FILTER(expression) keeps only the solutions for which the expression is true.

Examples use the sample data.

Example ​

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  PREFIX ex:   <http://example.org/>
  SELECT ?name ?age
  WHERE { ?p foaf:name ?name ; ex:age ?age
          FILTER(?age >= 30 && REGEX(?name, "^a", "i")) }
$$);
--  {"age": "34", "name": "Alice"}

Supported operators and functions ​

KindIn FILTER
Comparison=, !=, <, >, <=, >=, sameTerm(a, b)
Lists?v IN (…), ?v NOT IN (…)
Logic&&, ||, !
Term testsisIRI, isLiteral, isBlank, BOUND
Parts of a termSTR, LANG, DATATYPE
StringsLCASE, UCASE, CONTAINS, STRSTARTS, STRENDS, REGEX (add "i" for case-insensitive); STRLEN inside <, >, <=, >=
Arithmetic+, -, *, / and ABS inside a comparison

Anything else is refused with SQLSTATE 0A000 and a message naming the expression. That includes FILTER EXISTS, FILTER NOT EXISTS, LANGMATCHES, IF, CONCAT, COALESCE, SUBSTR and the SPARQL functions not in the table. IF and CONCAT do work in BIND; for the rest, see Not supported.

Comparing values ​

<, >, <= and >= compare numbers by value:

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX ex: <http://example.org/>
  SELECT ?p WHERE { ?p ex:age ?a FILTER(?a > 33.5) }
  ORDER BY ?p
$$);
--  {"p": "http://example.org/alice"}
--  {"p": "http://example.org/bob"}

= and != compare RDF terms exactly: the value, the datatype and the language tag must all match. FILTER(?a = 34) finds Alice; FILTER(?a = 34.0) finds nobody, because 34.0 is an xsd:decimal and the stored 34 is an xsd:integer. In the same way, "chat"@fr is not equal to "chat": compare STR(?label) = "chat" to ignore the tag.

IN tests against a list:

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX ex: <http://example.org/>
  SELECT ?p WHERE { ?p ex:age ?a FILTER(?a IN (29, 41)) }
  ORDER BY ?p
$$);
--  {"p": "http://example.org/bob"}
--  {"p": "http://example.org/carol"}

IRIs and term types ​

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  SELECT ?s ?o
  WHERE { ?s ?p ?o FILTER(isIRI(?o) && ?p = foaf:knows) }
  ORDER BY ?s ?o
$$);
--  {"o": "http://example.org/bob", "s": "http://example.org/alice"}
--  {"o": "http://example.org/carol", "s": "http://example.org/alice"}
--  {"o": "http://example.org/carol", "s": "http://example.org/bob"}

!= on a predicate variable excludes a property. This is also the way to write what a negated property path !(foaf:knows) would mean:

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  PREFIX ex:   <http://example.org/>
  SELECT ?p ?o WHERE { ex:bob ?p ?o FILTER(?p != foaf:knows) }
  ORDER BY ?p
$$);
--  {"o": "41", "p": "http://example.org/age"}
--  {"o": "http://xmlns.com/foaf/0.1/Person", "p": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"}
--  {"o": "Bob", "p": "http://xmlns.com/foaf/0.1/name"}

Language tags ​

LANGMATCHES is not supported; compare LANG(?x) instead. This example adds a small graph inside a transaction and rolls it back:

sql
BEGIN;
SELECT pgrdf.add_graph('http://example.org/labels');
SELECT pgrdf.parse_turtle($$
@prefix ex:   <http://example.org/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
ex:cat rdfs:label "cat"@en , "chat"@fr , "Katze"@de .
$$, pgrdf.graph_id('http://example.org/labels'));

SELECT * FROM pgrdf.sparql($$
  PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  SELECT ?l WHERE { ?s rdfs:label ?l FILTER(LANG(?l) = "fr") }
$$);
--  {"l": "chat"}
ROLLBACK;

LANG(?l) = "fr" matches the tag exactly. To include regional tags such as fr-CA, use STRSTARTS(LANG(?l), "fr"). Language tags come back in lower case (fr-ca).

Missing values ​

BOUND(?v) is true when a variable has a value. Combined with OPTIONAL, FILTER(!BOUND(?v)) finds solutions where something is absent.

pgRDF is released under the MIT license. Documentation built with VitePress, served via GitHub Pages.