Loading RDF Data
Grafeo includes zero-dependency parsers for W3C RDF serialization formats. Turtle and N-Triples support both batch (replace-all) and streaming (incremental, memory-bounded) loading. N-Quads is supported for export.
Loading a file or text into a database¶
The database loads a Turtle or N-Triples file, or text, into the default graph or a named graph in one bulk write: the input is parsed first, nothing is inserted when a line does not parse (the error names the line), and the triples go to the WAL as one group, so a persistent database keeps all of them or none after a crash. A load reports no change data capture events. Each call returns how many triples were new in its graph.
A named graph is given by its IRI, without angle brackets, and is created when it does not exist: its triples are where INSERT DATA { GRAPH <iri> { ... } } puts them.
import grafeo
db = grafeo.GrafeoDB("people.grafeo")
db.load_rdf("people.ttl") # the format from the extension
db.load_rdf("data.txt", format="ntriples")
db.load_rdf("cities.nt", graph="http://example.org/cities")
db.load_rdf_text(
'<http://example.org/alix> <http://example.org/city> "Amsterdam" .',
"ntriples",
graph="http://example.org/cities",
)
use grafeo::{GrafeoDB, RdfFormat};
let db = GrafeoDB::open("people.grafeo")?;
db.load_rdf("people.ttl", None)?;
db.load_rdf_into("cities.nt", None, Some("http://example.org/cities"))?;
db.load_rdf_text(
"<http://example.org/alix> <http://example.org/city> \"Amsterdam\" .",
RdfFormat::NTriples,
Some("http://example.org/cities"),
)?;
The store-level parsers below load an RdfStore directly, without the WAL.
Turtle¶
Turtle is the most common human-readable RDF format, supporting prefix declarations, predicate lists (;), object lists (,), blank nodes, typed literals and the a shorthand for rdf:type.
Turtle batch load (Rust)¶
Replaces the store contents with the parsed triples:
use grafeo_core::graph::rdf::RdfStore;
let store = RdfStore::new();
let result = store.load_turtle(r#"
@prefix ex: <http://example.org/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
ex:alix a foaf:Person ; foaf:name "Alix" ; foaf:knows ex:gus .
ex:gus foaf:name "Gus" .
"#)?;
println!("{} triples loaded", result.triple_count);
Turtle streaming load (Rust)¶
Inserts triples incrementally in batches of configurable size, bounding memory regardless of document size. Does not replace existing data:
The batch_size parameter controls how many triples are buffered before flushing to the store. 10,000 is a good default: small enough to cap memory, large enough to amortize lock overhead.
Loading via SPARQL¶
Python loads a file or text with load_rdf and load_rdf_text (see Loading a file or text into a database). The other bindings have no Turtle or N-Triples loader yet: from those, send the triples as a SPARQL INSERT DATA statement instead. N-Triples lines can go into INSERT DATA { ... } as they are. Turtle's @prefix ex: <...> . lines are not SPARQL: write each one as PREFIX ex: <...> (no @, no final dot) before INSERT DATA, and put the rest of the Turtle inside the braces:
PREFIX ex: <http://example.org/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
INSERT DATA {
ex:alix foaf:name "Alix" ;
foaf:knows ex:gus .
}
N-Triples¶
N-Triples is a line-based subset of Turtle with no prefixes, one triple per line. Its simplicity makes it ideal for streaming large datasets.
N-Triples batch load (Rust)¶
use std::io::BufReader;
let reader = BufReader::new(file);
let result = store.load_ntriples(reader)?;
N-Triples streaming load (Rust)¶
Parses line-by-line from a buffered reader, never holding the entire file in memory:
use std::io::BufReader;
let reader = BufReader::new(file);
let count = store.load_ntriples_streaming(reader, 10_000)?;
Serialization¶
Turtle export¶
Groups triples by subject with predicate/object shorthand for compact output.
N-Quads export¶
N-Quads extends N-Triples with an optional fourth field for the graph name, producing a single stream that includes both the default graph and all named graphs:
Custom Sinks¶
For advanced use cases the TripleSink trait decouples parsing from storage. Three built-in implementations are provided:
| Sink | Purpose |
|---|---|
BatchInsertSink | Buffered insert into an RdfStore (used by streaming loaders) |
CountSink | Dry-run counting without storage, useful for validation |
VecSink | Collects all triples into a Vec<Triple> |
use grafeo_core::graph::rdf::{CountSink, TurtleParser};
let mut sink = CountSink::new();
TurtleParser::new().parse_into(turtle_str, &mut sink)?;
println!("{} triples parsed", sink.count());
Implement TripleSink on your own types to route triples to custom destinations (logging, deduplication, remote stores).
SPARQL LOAD Statement¶
The SPARQL Update LOAD statement is not supported yet: LOAD <file:///path/to/data.ttl> fails with an unsupported error, also with SILENT. Load a file with load_rdf (Rust or Python) instead, or send its triples as INSERT DATA (see Loading via SPARQL).