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
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')); -- → 5add_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
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:
{"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:
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');{"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:
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 } }');{"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:
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.comSELECT count(*) AS people_with_mbox
FROM pgrdf.sparql(
'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?m WHERE { ?s foaf:mbox ?m }');
-- → 2Next step
Add inference with Load → Reason → Query, or a conformance gate with Load → Validate → Query.