On this page· 3
Read records
- file format 6
- Rust SDK 1.0 preview
Goal: read the entities of a pack, then the records whose primary id starts with e1.
- 1. Build a
Filter.with_kindskeeps records whose kind is in the list;with_id_prefixkeeps records whose primary id starts with the given text. - 2. Pass it to
pack.records_filtered(&filter), or callpack.records()for every record. - 3. Call
as_entity()oras_relation()on a record to read its members as fields.
Needs the Rust SDK
filter_and_views.rsrust
// Read only some records, and look at entities and relations
// through typed views.
use plxi_sdk::{write, Filter, OpenOptions, Pack, Record};
fn main() -> Result<(), plxi_sdk::Error> {
let lines = [
r#"{"k":"ent","id":"e1","t":"Person","name":"Ada","salience":0.5}"#,
r#"{"k":"ent","id":"e2","t":"Person"}"#,
r#"{"k":"ent","id":"p1","t":"Place","name":"London"}"#,
r#"{"k":"rel","src":"e1","tgt":"p1","kind":"lives_in"}"#,
];
let records = lines
.iter()
.map(|l| Record::from_json_line(l))
.collect::<Result<Vec<_>, _>>()?;
let bytes = write(&records, None)?;
let pack = Pack::from_bytes(bytes, OpenOptions::default())?;
// By kind.
let only_entities = Filter::new().with_kinds(["ent"]);
let mut names = Vec::new();
for record in pack.records_filtered(&only_entities) {
let record = record?;
let entity = record
.as_entity()
.expect("an `ent` record has an entity view");
let name = entity.name.map(str::to_string);
names.push((entity.id.to_string(), entity.t.to_string(), name));
}
assert_eq!(names.len(), 3);
let first = (
"e1".to_string(),
"Person".to_string(),
Some("Ada".to_string()),
);
assert_eq!(names[0], first);
// By primary-id prefix. A relation's primary id is "src|tgt|kind".
let about_e1 = Filter::new().with_id_prefix("e1");
let ids: Vec<String> = pack
.records_filtered(&about_e1)
.map(|r| r.map(|rec| rec.primary_id().to_string()))
.collect::<Result<_, _>>()?;
assert_eq!(ids, ["e1", "e1|p1|lives_in"]);
// Both conditions at once: every field that is set must match.
let both = Filter::new().with_kinds(["rel"]).with_id_prefix("e1");
let rels: Vec<Record> =
pack.records_filtered(&both).collect::<Result<_, _>>()?;
let view = rels[0]
.as_relation()
.expect("a `rel` record has a relation view");
assert_eq!((view.src, view.tgt, view.kind), ("e1", "p1", "lives_in"));
println!("{} -[{}]-> {}", view.src, view.kind, view.tgt);
Ok(())
}
Output
e1 -[lives_in]-> p1Ran with cargo run --example 03_filter_and_views · exit status 0
- Records come back in file order, which is sort-key order. Each item is a
Result<Record>. - When both conditions are set, a record must meet both.
- A relation's primary id is
src|tgt|kind, so an id prefix selects relations by their source. - Only
entandrelhave typed views. Every other kind is read as JSON withRecord::to_json_value. - An error in the record stream always passes the filter, so a filtered read does not hide a damaged line. A body that is not UTF-8 yields one error and nothing else.
Record::json_linereturns the writer's spelling of the record, which may differ from the text that was read. Records and kinds