Query with SPARQL¶
OntoEnv evaluates SPARQL in Rust, reading directly from its on-disk storage.
You get to that engine through ordinary rdflib entry points. Pick the
scope you need:
You want to query |
Use |
Returns |
|---|---|---|
One ontology plus its imports |
|
a read-only |
An explicit set of graphs |
|
a read-only |
The whole environment, named graphs intact |
|
a read-only |
Query an imports closure¶
view, imported = env.get_closure("https://brickschema.org/schema/1.4/Brick")
rows = view.query("""
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX brick: <https://brickschema.org/schema/Brick#>
SELECT ?sub WHERE { ?sub rdfs:subClassOf* brick:Equipment }
""")
for row in rows:
print(row.sub)
The query is scoped to the graphs in the closure and sees them as one flattened graph. Nothing is materialized in Python.
Recursive property paths on rdfs:subClassOf, rdfs:subPropertyOf, and
owl:sameAs are answered from a precomputed transitive-closure table, which
avoids materializing the closure as a Python graph. See
Performance for measurements and their scope.
Query across named graphs¶
When you need to know which graph a triple came from, use the dataset view:
dataset = env.get_dataset()
rows = dataset.query("""
SELECT ?g (COUNT(*) AS ?triples) WHERE {
GRAPH ?g { ?s ?p ?o }
} GROUP BY ?g
""")
for row in rows:
print(row.g, int(row.triples))
Each named graph is keyed by its ontology IRI, and the namespaces OntoEnv knows about are already bound. To pull one graph out of the dataset:
from rdflib import URIRef
brick = dataset.graph(URIRef("https://brickschema.org/schema/1.4/Brick"))
print(len(brick))
A dataset reflects the environment as of the moment you asked for it. After mutating the environment, ask again or refresh in place:
env.add("./ontologies/new.ttl")
env.flush()
env.refresh_dataset(dataset)
These calls form a sequence. add changes the environment, flush
publishes the pending store snapshot, and refresh_dataset rebinds the
existing dataset to that snapshot. Without the final call, dataset remains
the point-in-time view returned earlier.
Query a set of graphs you choose¶
view, graph_iris = env.get_union([
"https://example.org/a",
"https://example.org/b",
])
# Expand each listed graph's transitive imports too
view, graph_iris = env.get_union(
["https://example.org/a"],
include_closures=True,
)
Unlike get_closure, a union is a raw merge: no import stripping, no
ontology-declaration collapsing, and no de-duplication across graphs. Use it
when you want exactly the graphs you named and nothing done to them.
Use the rdflib plugin¶
Importing ontoenv registers an rdflib store plugin named "ontoenv".
Constructing the plugin by name creates an empty store; it cannot infer which
environment to read. Bind it explicitly:
from rdflib import Dataset
import ontoenv # registers the plugin
dataset = Dataset(store="ontoenv")
dataset.store.refresh_from_env(env)
Use env.get_dataset() when you control construction. The plugin form is
for code that requires an rdflib store name; refresh_from_env supplies the
environment that plugin registration alone cannot provide.
Query from the command line¶
The CLI has no query subcommand. Export the graph you want and query it
with your usual tooling:
$ ontoenv closure https://example.org/site closure.ttl
What is not supported¶
SPARQL Update. The exposed store is a read-only snapshot. Mutate the environment through
OntoEnvmethods, then take a fresh view.Writing through the store.
add,addN, andremoveraiseValueErroron bothViewGraphandOntoEnvStore.
For a mutable graph you can query with rdflib’s own engine, use copy_closure
or copy_dataset.
See also
ViewGraph and OntoEnvStore for the full ViewGraph and
OntoEnvStore surface, and python/demo_rdflib_store.py in the
repository for a runnable example.