Regional Sales Analytics with Uni (Rust)¶
Combining graph traversal with columnar aggregation across multiple regions and product categories.
In [ ]:
Copied!
:dep uni-db = { path = "../../../crates/uni" }
:dep tokio = { version = "1", features = ["full"] }
:dep serde_json = "1"
:dep uni-db = { path = "../../../crates/uni" }
:dep tokio = { version = "1", features = ["full"] }
:dep serde_json = "1"
In [ ]:
Copied!
use uni::{Uni, DataType, IndexType, ScalarType, VectorMetric, VectorAlgo, VectorIndexCfg};
use std::collections::HashMap;
use serde_json::json;
// Helper macro to run async code in evcxr
macro_rules! run {
($e:expr) => {
tokio::runtime::Runtime::new().unwrap().block_on($e)
};
}
use uni::{Uni, DataType, IndexType, ScalarType, VectorMetric, VectorAlgo, VectorIndexCfg};
use std::collections::HashMap;
use serde_json::json;
// Helper macro to run async code in evcxr
macro_rules! run {
($e:expr) => {
tokio::runtime::Runtime::new().unwrap().block_on($e)
};
}
In [ ]:
Copied!
let db_path = "./sales_db";
// Clean up any existing database
if std::path::Path::new(db_path).exists() {
std::fs::remove_dir_all(db_path).unwrap();
}
let db = run!(Uni::open(db_path).build()).unwrap();
println!("Opened database at {}", db_path);
let db_path = "./sales_db";
// Clean up any existing database
if std::path::Path::new(db_path).exists() {
std::fs::remove_dir_all(db_path).unwrap();
}
let db = run!(Uni::open(db_path).build()).unwrap();
println!("Opened database at {}", db_path);
1. Schema¶
In [ ]:
Copied!
run!(async {
db.schema()
.label("Region")
.property("name", DataType::String)
.label("Category")
.property("name", DataType::String)
.label("Order")
.property("amount", DataType::Float64)
.edge_type("SHIPPED_TO", &["Order"], &["Region"])
.edge_type("IN_CATEGORY", &["Order"], &["Category"])
.apply()
.await
}).unwrap();
println!("Sales analytics schema created");
run!(async {
db.schema()
.label("Region")
.property("name", DataType::String)
.label("Category")
.property("name", DataType::String)
.label("Order")
.property("amount", DataType::Float64)
.edge_type("SHIPPED_TO", &["Order"], &["Region"])
.edge_type("IN_CATEGORY", &["Order"], &["Category"])
.apply()
.await
}).unwrap();
println!("Sales analytics schema created");
2. Ingest Data¶
4 regions, 3 categories, 27 orders distributed non-uniformly.
In [ ]:
Copied!
// Regions
let region_props = vec![
HashMap::from([("name".to_string(), json!("North"))]),
HashMap::from([("name".to_string(), json!("South"))]),
HashMap::from([("name".to_string(), json!("East"))]),
HashMap::from([("name".to_string(), json!("West"))]),
];
let region_vids = run!(db.bulk_insert_vertices("Region", region_props)).unwrap();
let (north, south, east, west) = (region_vids[0], region_vids[1], region_vids[2], region_vids[3]);
// Categories
let cat_props = vec![
HashMap::from([("name".to_string(), json!("Electronics"))]),
HashMap::from([("name".to_string(), json!("Apparel"))]),
HashMap::from([("name".to_string(), json!("Home & Garden"))]),
];
let cat_vids = run!(db.bulk_insert_vertices("Category", cat_props)).unwrap();
let (electronics, apparel, home_garden) = (cat_vids[0], cat_vids[1], cat_vids[2]);
// Orders: (amount, region_vid, category_vid)
let orders_raw = vec![
// East: high-value electronics
(1200.0, east, electronics), (980.0, east, electronics),
(450.0, east, apparel), (120.0, east, apparel),
(85.0, east, apparel), (60.0, east, home_garden),
// West: strong Home & Garden
(890.0, west, home_garden), (620.0, west, home_garden),
(450.0, west, home_garden), (340.0, west, home_garden),
(500.0, west, electronics), (210.0, west, apparel),
(180.0, west, apparel),
// South: most electronics
(750.0, south, electronics), (680.0, south, electronics),
(590.0, south, electronics), (520.0, south, electronics),
(480.0, south, electronics), (300.0, south, apparel),
(250.0, south, home_garden),
// North: balanced mix
(400.0, north, electronics), (350.0, north, electronics),
(280.0, north, apparel), (260.0, north, apparel),
(240.0, north, apparel), (320.0, north, home_garden),
(290.0, north, home_garden),
];
let order_props: Vec<_> = orders_raw.iter()
.map(|(amt, _, _)| HashMap::from([("amount".to_string(), json!(*amt))]))
.collect();
let order_vids = run!(db.bulk_insert_vertices("Order", order_props)).unwrap();
let shipped_edges: Vec<_> = order_vids.iter().zip(orders_raw.iter())
.map(|(&ov, &(_, rv, _))| (ov, rv, HashMap::new()))
.collect();
run!(db.bulk_insert_edges("SHIPPED_TO", shipped_edges)).unwrap();
let category_edges: Vec<_> = order_vids.iter().zip(orders_raw.iter())
.map(|(&ov, &(_, _, cv))| (ov, cv, HashMap::new()))
.collect();
run!(db.bulk_insert_edges("IN_CATEGORY", category_edges)).unwrap();
run!(db.flush()).unwrap();
println!("Inserted {} orders", order_vids.len());
// Regions
let region_props = vec![
HashMap::from([("name".to_string(), json!("North"))]),
HashMap::from([("name".to_string(), json!("South"))]),
HashMap::from([("name".to_string(), json!("East"))]),
HashMap::from([("name".to_string(), json!("West"))]),
];
let region_vids = run!(db.bulk_insert_vertices("Region", region_props)).unwrap();
let (north, south, east, west) = (region_vids[0], region_vids[1], region_vids[2], region_vids[3]);
// Categories
let cat_props = vec![
HashMap::from([("name".to_string(), json!("Electronics"))]),
HashMap::from([("name".to_string(), json!("Apparel"))]),
HashMap::from([("name".to_string(), json!("Home & Garden"))]),
];
let cat_vids = run!(db.bulk_insert_vertices("Category", cat_props)).unwrap();
let (electronics, apparel, home_garden) = (cat_vids[0], cat_vids[1], cat_vids[2]);
// Orders: (amount, region_vid, category_vid)
let orders_raw = vec![
// East: high-value electronics
(1200.0, east, electronics), (980.0, east, electronics),
(450.0, east, apparel), (120.0, east, apparel),
(85.0, east, apparel), (60.0, east, home_garden),
// West: strong Home & Garden
(890.0, west, home_garden), (620.0, west, home_garden),
(450.0, west, home_garden), (340.0, west, home_garden),
(500.0, west, electronics), (210.0, west, apparel),
(180.0, west, apparel),
// South: most electronics
(750.0, south, electronics), (680.0, south, electronics),
(590.0, south, electronics), (520.0, south, electronics),
(480.0, south, electronics), (300.0, south, apparel),
(250.0, south, home_garden),
// North: balanced mix
(400.0, north, electronics), (350.0, north, electronics),
(280.0, north, apparel), (260.0, north, apparel),
(240.0, north, apparel), (320.0, north, home_garden),
(290.0, north, home_garden),
];
let order_props: Vec<_> = orders_raw.iter()
.map(|(amt, _, _)| HashMap::from([("amount".to_string(), json!(*amt))]))
.collect();
let order_vids = run!(db.bulk_insert_vertices("Order", order_props)).unwrap();
let shipped_edges: Vec<_> = order_vids.iter().zip(orders_raw.iter())
.map(|(&ov, &(_, rv, _))| (ov, rv, HashMap::new()))
.collect();
run!(db.bulk_insert_edges("SHIPPED_TO", shipped_edges)).unwrap();
let category_edges: Vec<_> = order_vids.iter().zip(orders_raw.iter())
.map(|(&ov, &(_, _, cv))| (ov, cv, HashMap::new()))
.collect();
run!(db.bulk_insert_edges("IN_CATEGORY", category_edges)).unwrap();
run!(db.flush()).unwrap();
println!("Inserted {} orders", order_vids.len());
3. Revenue by Region¶
Total revenue and order count per region, ordered by revenue.
In [ ]:
Copied!
let query_region = r#"
MATCH (r:Region)<-[:SHIPPED_TO]-(o:Order)
RETURN r.name AS region, COUNT(o) AS order_count, SUM(o.amount) AS total_revenue
ORDER BY total_revenue DESC
"#;
let results = run!(db.query(query_region)).unwrap();
println!("Revenue by region:");
for row in &results.rows {
println!(" {:?}", row);
}
assert!(results.rows.len() == 4, "Expected 4 regions, got {}", results.rows.len());
let query_region = r#"
MATCH (r:Region)<-[:SHIPPED_TO]-(o:Order)
RETURN r.name AS region, COUNT(o) AS order_count, SUM(o.amount) AS total_revenue
ORDER BY total_revenue DESC
"#;
let results = run!(db.query(query_region)).unwrap();
println!("Revenue by region:");
for row in &results.rows {
println!(" {:?}", row);
}
assert!(results.rows.len() == 4, "Expected 4 regions, got {}", results.rows.len());
4. Region × Category Breakdown¶
12-row breakdown showing revenue for every region/category pair.
In [ ]:
Copied!
let query_breakdown = r#"
MATCH (r:Region)<-[:SHIPPED_TO]-(o:Order)-[:IN_CATEGORY]->(c:Category)
RETURN r.name AS region, c.name AS category,
COUNT(o) AS orders, SUM(o.amount) AS revenue
ORDER BY region, revenue DESC
"#;
let results = run!(db.query(query_breakdown)).unwrap();
println!("Region x Category breakdown ({} rows):", results.rows.len());
for row in &results.rows {
println!(" {:?}", row);
}
assert!(results.rows.len() == 12, "Expected 12 rows (4x3), got {}", results.rows.len());
let query_breakdown = r#"
MATCH (r:Region)<-[:SHIPPED_TO]-(o:Order)-[:IN_CATEGORY]->(c:Category)
RETURN r.name AS region, c.name AS category,
COUNT(o) AS orders, SUM(o.amount) AS revenue
ORDER BY region, revenue DESC
"#;
let results = run!(db.query(query_breakdown)).unwrap();
println!("Region x Category breakdown ({} rows):", results.rows.len());
for row in &results.rows {
println!(" {:?}", row);
}
assert!(results.rows.len() == 12, "Expected 12 rows (4x3), got {}", results.rows.len());
5. Top Orders per Region¶
Highest-value orders in each region.
In [ ]:
Copied!
let query_top = r#"
MATCH (r:Region)<-[:SHIPPED_TO]-(o:Order)
RETURN r.name AS region, o.amount AS amount
ORDER BY region, amount DESC
"#;
let results = run!(db.query(query_top)).unwrap();
println!("All orders by region (DESC):");
println!(" {} total order rows", results.rows.len());
// East should lead with $1200
println!(" First row (should be East $1200): {:?}", results.rows.first());
let query_top = r#"
MATCH (r:Region)<-[:SHIPPED_TO]-(o:Order)
RETURN r.name AS region, o.amount AS amount
ORDER BY region, amount DESC
"#;
let results = run!(db.query(query_top)).unwrap();
println!("All orders by region (DESC):");
println!(" {} total order rows", results.rows.len());
// East should lead with $1200
println!(" First row (should be East $1200): {:?}", results.rows.first());
6. Best Category per Region¶
The highest-revenue category for each region.
In [ ]:
Copied!
let query_best = r#"
MATCH (r:Region)<-[:SHIPPED_TO]-(o:Order)-[:IN_CATEGORY]->(c:Category)
RETURN r.name AS region, c.name AS category, SUM(o.amount) AS revenue
ORDER BY region, revenue DESC
"#;
let results = run!(db.query(query_best)).unwrap();
println!("Best category per region (first result per region):");
let mut seen_regions = std::collections::HashSet::new();
for row in &results.rows {
// rows are sorted by region, revenue DESC — take first per region
if let Some(region_val) = row.values.first() {
let region_str = format!("{:?}", region_val);
if seen_regions.insert(region_str.clone()) {
println!(" {}: {:?}", region_str, row);
}
}
}
// Each region has a different best category (electronics, home & garden, etc.)
let query_best = r#"
MATCH (r:Region)<-[:SHIPPED_TO]-(o:Order)-[:IN_CATEGORY]->(c:Category)
RETURN r.name AS region, c.name AS category, SUM(o.amount) AS revenue
ORDER BY region, revenue DESC
"#;
let results = run!(db.query(query_best)).unwrap();
println!("Best category per region (first result per region):");
let mut seen_regions = std::collections::HashSet::new();
for row in &results.rows {
// rows are sorted by region, revenue DESC — take first per region
if let Some(region_val) = row.values.first() {
let region_str = format!("{:?}", region_val);
if seen_regions.insert(region_str.clone()) {
println!(" {}: {:?}", region_str, row);
}
}
}
// Each region has a different best category (electronics, home & garden, etc.)