Skip to content

searchPattern — Load → Query ​

The simplest semantic process: get RDF in and ask questions of it. No inference, no validation, no carving.

When to use it ​

You have RDF and you want to query it with SPARQL, joined if you like with regular SQL. Query isn't bound by the one-session limit that reasoning is, so this pattern needs no carving however large the graph.

A worked scenario — people and their mailboxes ​

Three people; two have a mailbox, one does not.

Step 1 — load the data ​

sql
SELECT pgrdf.add_graph('http://example.org/people');   -- → 1
SELECT pgrdf.parse_turtle('
@prefix ex:   <http://example.com/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

ex:alice foaf:name "Alice" ; foaf:mbox <mailto:alice@example.com> .
ex:bob   foaf:name "Bob" .
ex:carol foaf:name "Carol" ; foaf:mbox <mailto:carol@example.com> .
', pgrdf.graph_id('http://example.org/people'));       -- → 5

add_graph creates the graph and returns its id. graph_id looks the id up by IRI, so you never have to remember the number.

Step 2 — a basic query ​

sql
SELECT * FROM pgrdf.sparql(
  'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
   SELECT ?n WHERE { ?s foaf:name ?n } ORDER BY ?n');

One JSONB row per solution:

json
{"n": "Alice"}
{"n": "Bob"}
{"n": "Carol"}

Step 3 — refine with OPTIONAL ​

Pull in the mailbox where it exists, without dropping the people who have none. That is what OPTIONAL does:

sql
SELECT * FROM pgrdf.sparql(
  'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
   SELECT ?n ?m
   WHERE { ?s foaf:name ?n .
           OPTIONAL { ?s foaf:mbox ?m } }
   ORDER BY ?n');
json
{"m": "mailto:alice@example.com", "n": "Alice"}
{"m": null, "n": "Bob"}
{"m": "mailto:carol@example.com", "n": "Carol"}

Bob keeps his row. His missing mailbox comes back as null instead of removing him from the result.

Step 4 — scope the query to one graph ​

A query without a GRAPH clause searches every graph in the database. Once you load a second dataset, name the graph you mean:

sql
SELECT * FROM pgrdf.sparql(
  'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
   SELECT (COUNT(?s) AS ?people)
   WHERE { GRAPH <http://example.org/people> { ?s foaf:name ?n } }');
json
{"people": "3"}

Every value comes back as a string, numbers included. Cast in SQL when you need a number.

Compose with regular SQL ​

pgrdf.sparql is a set-returning function, so its result is a table you can unpack, filter, aggregate or join against your own tables:

sql
SELECT r ->> 'n' AS name, r ->> 'm' AS mailbox
FROM pgrdf.sparql(
  'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
   SELECT ?n ?m WHERE { ?s foaf:name ?n . OPTIONAL { ?s foaf:mbox ?m } }
   ORDER BY ?n') AS r;
 name  |         mailbox
-------+--------------------------
 Alice | mailto:alice@example.com
 Bob   |
 Carol | mailto:carol@example.com
sql
SELECT count(*) AS people_with_mbox
FROM pgrdf.sparql(
  'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
   SELECT ?m WHERE { ?s foaf:mbox ?m }');
--  → 2

Next step ​

Add inference with Load → Reason → Query, or a conformance gate with Load → Validate → Query.

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