Example 5: Merge
- file format 6
- Rust SDK 1.0 preview
Needs the Rust SDK
Merge two packs that disagree about one entity, with the default strategy and with union.
05_merge.rsrust
// Merge two packs and choose how a conflict between two versions of
// one entity is settled.
use plxi_sdk::{
merge, write, MergeOptions, MergeStrategy, OpenOptions, Pack, Record,
};
type Result<T> = std::result::Result<T, plxi_sdk::Error>;
fn pack(lines: &[&str]) -> Result<Vec<u8>> {
let records: Vec<Record> = lines
.iter()
.map(|l| Record::from_json_line(l))
.collect::<Result<_>>()?;
write(&records, None)
}
fn name_of_e1(bytes: Vec<u8>) -> Result<Option<String>> {
let pack = Pack::from_bytes(bytes, OpenOptions::default())?;
for record in pack.records() {
let record = record?;
if let Some(e) = record.as_entity() {
if e.id == "e1" {
return Ok(e.name.map(str::to_string));
}
}
}
Ok(None)
}
fn main() -> Result<()> {
let a = pack(&[
r#"{"k":"ent","id":"e1","t":"Person","salience":0.5}"#,
r#"{"k":"ent","id":"e2","t":"Person"}"#,
r#"{"k":"rel","src":"e1","tgt":"e2","kind":"knows"}"#,
])?;
let b = pack(&[
r#"{"k":"ent","id":"e1","t":"Person","salience":0.75,"name":"B"}"#,
r#"{"k":"ent","id":"e3","t":"Person"}"#,
r#"{"k":"rel","src":"e1","tgt":"e3","kind":"knows"}"#,
])?;
// Default strategy: the incoming entity wins only with a strictly
// greater salience. 0.75 > 0.5, so pack b's e1 is taken.
let default = MergeOptions::default();
assert_eq!(default.strategy, MergeStrategy::HigherSalience);
let (merged, report) = merge(&[&a, &b], &default)?;
assert_eq!((report.records_inserted, report.conflicts), (5, 1));
assert_eq!(name_of_e1(merged)?, Some("B".to_string()));
println!("{}", report.to_json());
// `Union` keeps the record that was there first.
let union = MergeOptions::with_strategy(MergeStrategy::Union);
let (merged, _) = merge(&[&a, &b], &union)?;
assert_eq!(name_of_e1(merged)?, None);
// Strategies have stable names, for configuration files.
assert_eq!(MergeStrategy::Latest.as_str(), "latest");
let manual = MergeStrategy::from_name("manual");
assert_eq!(manual, Some(MergeStrategy::Manual));
assert_eq!(MergeStrategy::from_name("newest"), None);
Ok(())
}
Output
{"records_inserted":5,"records_updated":1,"records_skipped":0,"stubs_resolved":0,"conflicts":1,"sections_merged":0,"sections_deduped":0}Ran with cargo run --example 05_merge · exit status 0
Explained in: Merge packs