getting_started/
getting_started.rs

1use spatio::{Point, SetOptions, Spatio, TemporalPoint};
2use std::time::{Duration, UNIX_EPOCH};
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    // Initialize logging (set RUST_LOG=debug to see detailed logs)
6    env_logger::init();
7
8    println!("=== Spatio - Getting Started ===\n");
9
10    // Create an in-memory database
11    let mut db = Spatio::memory()?;
12    println!("✓ Created in-memory database\n");
13
14    // === BASIC KEY-VALUE STORAGE ===
15    println!("1. Basic Key-Value Storage");
16    println!("---------------------------");
17
18    db.insert("user:123", b"John Doe", None)?;
19    let value = db.get("user:123")?.unwrap();
20    println!("   Stored: user:123 = {}", String::from_utf8_lossy(&value));
21
22    // Store data with TTL (time-to-live)
23    let ttl_options = SetOptions::with_ttl(Duration::from_secs(5));
24    db.insert("session:abc", b"expires_soon", Some(ttl_options))?;
25    println!("   Stored session data with 5-second TTL\n");
26
27    // === SPATIAL OPERATIONS ===
28    println!("2. Spatial Point Storage");
29    println!("------------------------");
30
31    // Store geographic points (lon, lat format)
32    let nyc = Point::new(-74.0060, 40.7128);
33    let london = Point::new(-0.1278, 51.5074);
34    let paris = Point::new(2.3522, 48.8566);
35
36    db.insert_point("cities", &nyc, b"New York", None)?;
37    db.insert_point("cities", &london, b"London", None)?;
38    db.insert_point("cities", &paris, b"Paris", None)?;
39    println!("   Stored 3 cities with automatic spatial indexing");
40
41    // Find nearby cities within radius (in meters)
42    let nearby = db.query_within_radius("cities", &london, 500_000.0, 10)?;
43    println!("   Found {} cities within 500km of London:", nearby.len());
44    for (_, data, _) in &nearby {
45        println!("     - {}", String::from_utf8_lossy(data));
46    }
47    println!();
48
49    // === SPATIAL QUERY METHODS ===
50    println!("3. Spatial Query Methods");
51    println!("------------------------");
52
53    // Check if any points exist within radius
54    let has_nearby = db.intersects_radius("cities", &paris, 1_000_000.0)?;
55    println!("   Cities within 1000km of Paris: {}", has_nearby);
56
57    // Count points within radius
58    let count = db.count_within_radius("cities", &nyc, 6_000_000.0)?;
59    println!("   Cities within 6000km of NYC: {}", count);
60
61    // Find points within bounding box (min_lon, min_lat, max_lon, max_lat)
62    let results = db.find_within_bounds("cities", -10.0, 40.0, 10.0, 55.0, 10)?;
63    println!("   Cities in European bounding box: {}", results.len());
64    for (_point, data) in results {
65        println!("     - {}", String::from_utf8_lossy(&data));
66    }
67    println!();
68
69    // === ATOMIC OPERATIONS ===
70    println!("4. Atomic Batch Operations");
71    println!("---------------------------");
72
73    db.atomic(|batch| {
74        batch.insert("sensor:temp", b"22.5C", None)?;
75        batch.insert("sensor:humidity", b"65%", None)?;
76        batch.insert("sensor:pressure", b"1013 hPa", None)?;
77        Ok(())
78    })?;
79    println!("   Atomically inserted 3 sensor readings\n");
80
81    // === TRAJECTORY TRACKING ===
82    println!("5. Trajectory Tracking");
83    println!("----------------------");
84
85    let vehicle_path = vec![
86        TemporalPoint {
87            point: Point::new(-74.0060, 40.7128),
88            timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
89        },
90        TemporalPoint {
91            point: Point::new(-74.0040, 40.7150),
92            timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
93        },
94        TemporalPoint {
95            point: Point::new(-74.0020, 40.7172),
96            timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
97        },
98    ];
99
100    db.insert_trajectory("vehicle:truck001", &vehicle_path, None)?;
101    println!(
102        "   Stored vehicle trajectory with {} waypoints",
103        vehicle_path.len()
104    );
105
106    // Query trajectory for time range
107    let path_segment = db.query_trajectory("vehicle:truck001", 1640995200, 1640995320)?;
108    println!(
109        "   Retrieved {} waypoints from trajectory\n",
110        path_segment.len()
111    );
112
113    // === DATABASE STATS ===
114    println!("6. Database Statistics");
115    println!("----------------------");
116
117    let stats = db.stats();
118    println!("   Total keys stored: {}", stats.key_count);
119    println!("   Total operations: {}\n", stats.operations_count);
120
121    // === TTL DEMONSTRATION (LAZY) ===
122    println!("7. TTL Expiration (Lazy Deletion)");
123    println!("----------------------------------");
124    println!("   Waiting 6 seconds for TTL expiration...");
125    std::thread::sleep(Duration::from_secs(6));
126
127    match db.get("session:abc")? {
128        Some(_) => println!("   Session still active (unexpected)"),
129        None => println!("   ✓ Session expired (lazy check on read)"),
130    }
131
132    // Manual cleanup
133    let removed = db.cleanup_expired()?;
134    println!("   Cleaned up {} expired keys from storage\n", removed);
135
136    println!("=== Getting Started Complete! ===");
137    println!("\nKey Features Demonstrated:");
138    println!("  • Simple key-value storage");
139    println!("  • Automatic spatial indexing");
140    println!("  • Radius-based queries");
141    println!("  • Bounding box queries");
142    println!("  • Trajectory tracking");
143    println!("  • TTL support (lazy expiration + manual cleanup)");
144    println!("  • Atomic operations");
145    println!("\nNext: Try 'spatial_queries' example for more advanced queries");
146
147    Ok(())
148}