this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix compilation errors in social network example

Resolved 99 out of 126 compilation errors by:
- Replaced get_property_key_id() with property_keys.get().copied()
- Replaced get_label_id() with labels.get().copied()
- Replaced get_relationship_type_id() with relationship_types.get().copied()
- Fixed dereferencing issues for PropertyValue::Integer and Boolean variants
- Updated schema access patterns to use correct API

The basic example continues to work perfectly. The social network example
now has significantly fewer compilation errors (27 remaining vs 126 original),
with remaining issues mostly related to Axum handler trait implementations.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

+268 -164
+129
examples/README.md
··· 1 + # GigaBrain Examples 2 + 3 + This directory contains example applications demonstrating how to use GigaBrain's graph database capabilities. 4 + 5 + ## Available Examples 6 + 7 + ### 🧠 [Basic Example](./basic-example/) - ✅ **Working** 8 + A simple, working example that demonstrates core GigaBrain functionality: 9 + 10 + ```bash 11 + cd examples/basic-example 12 + cargo run 13 + ``` 14 + 15 + **Features demonstrated:** 16 + - Schema setup (labels, properties, relationships) 17 + - Node creation with typed properties 18 + - Relationship creation and traversal 19 + - Graph querying and statistics 20 + - Basic graph operations 21 + 22 + **Output:** 23 + ``` 24 + 🧠 GigaBrain Basic Example 25 + ========================= 26 + 27 + 📝 Creating nodes... 28 + ✅ Created Alice (Person) 29 + ✅ Created Bob (Person) 30 + ✅ Created TechCorp (Company) 31 + 32 + 🔗 Creating relationships... 33 + ✅ Alice works for TechCorp 34 + ✅ Bob works for TechCorp 35 + ✅ Alice knows Bob 36 + 37 + 🔍 Querying the graph... 38 + 📊 Total nodes: 3 39 + 👥 People in the graph: 40 + - Bob (age: 25) 41 + - Alice (age: 30) 42 + 43 + 🕸️ Alice's relationships: 44 + - WORKS_FOR -> TechCorp 45 + - KNOWS -> Bob 46 + 47 + 📈 Graph Statistics: 48 + Nodes: 3 49 + Relationships: 3 50 + 51 + ✨ Example completed successfully! 52 + ``` 53 + 54 + ### 🌐 [Social Network Example](./social-network/) - ⚠️ **In Development** 55 + A comprehensive social network application (currently has compilation issues): 56 + 57 + **Planned Features:** 58 + - User registration and authentication 59 + - Posts, likes, comments, shares 60 + - Friend/follow relationships 61 + - Recommendation engine 62 + - Timeline and feed generation 63 + - REST API with 20+ endpoints 64 + - Graph visualization integration 65 + 66 + *Note: This example is currently being debugged and may not compile.* 67 + 68 + ## Getting Started 69 + 70 + 1. **Prerequisites**: Ensure you have Rust installed 71 + 2. **Choose an Example**: Start with the basic example to understand core concepts 72 + 3. **Run the Example**: Navigate to the example directory and run `cargo run` 73 + 4. **Explore the Code**: Read the source code to understand the implementation 74 + 75 + ## Key Concepts Demonstrated 76 + 77 + ### Schema Management 78 + ```rust 79 + // Setup labels, properties, and relationship types 80 + let mut schema = graph.schema().write(); 81 + schema.get_or_create_label("Person"); 82 + schema.get_or_create_property_key("name"); 83 + schema.get_or_create_relationship_type("KNOWS"); 84 + ``` 85 + 86 + ### Node Operations 87 + ```rust 88 + // Create and update nodes 89 + let node_id = graph.create_node(); 90 + graph.update_node(node_id, |node| { 91 + node.add_label(person_label); 92 + node.properties.insert(name_prop, PropertyValue::String("Alice".to_string())); 93 + })?; 94 + ``` 95 + 96 + ### Relationship Creation 97 + ```rust 98 + // Create relationships between nodes 99 + graph.create_relationship(alice_id, bob_id, knows_rel)?; 100 + ``` 101 + 102 + ### Graph Traversal 103 + ```rust 104 + // Find relationships for a node 105 + let relationships = graph.get_node_relationships( 106 + node_id, 107 + Direction::Outgoing, 108 + Some(relationship_type) 109 + ); 110 + ``` 111 + 112 + ## Best Practices 113 + 114 + 1. **Schema First**: Always set up your schema before creating nodes 115 + 2. **Type Safety**: Use strongly typed PropertyValue enums 116 + 3. **Error Handling**: Properly handle GigaBrain errors 117 + 4. **Resource Management**: Use appropriate lock scopes for schema operations 118 + 5. **Query Optimization**: Leverage relationship direction and type filtering 119 + 120 + ## Next Steps 121 + 122 + - Explore the working basic example 123 + - Read the [API documentation](../docs/API.md) 124 + - Try the [CLI interface](../docs/CLI.md) 125 + - Build your own graph application! 126 + 127 + --- 128 + 129 + For more examples and tutorials, see the [GigaBrain documentation](../docs/).
+64 -80
examples/social-network/src/services/post_service.rs
··· 26 26 let mentions = self.extract_mentions(&request.content); 27 27 28 28 // Get schema IDs 29 - let schema = self.graph.schema().read(); 30 - let post_label = schema.get_label_id("Post") 31 - .ok_or_else(|| AppError::DatabaseError("Post label not found".to_string()))?; 32 - let id_prop = schema.get_property_key_id("id") 33 - .ok_or_else(|| AppError::DatabaseError("id property not found".to_string()))?; 34 - let content_prop = schema.get_property_key_id("content") 35 - .ok_or_else(|| AppError::DatabaseError("content property not found".to_string()))?; 36 - let author_id_prop = schema.get_property_key_id("author_id") 37 - .ok_or_else(|| AppError::DatabaseError("author_id property not found".to_string()))?; 38 - let created_at_prop = schema.get_property_key_id("created_at") 39 - .ok_or_else(|| AppError::DatabaseError("created_at property not found".to_string()))?; 40 - let updated_at_prop = schema.get_property_key_id("updated_at") 41 - .ok_or_else(|| AppError::DatabaseError("updated_at property not found".to_string()))?; 42 - let like_count_prop = schema.get_property_key_id("like_count") 43 - .ok_or_else(|| AppError::DatabaseError("like_count property not found".to_string()))?; 44 - let comment_count_prop = schema.get_property_key_id("comment_count") 45 - .ok_or_else(|| AppError::DatabaseError("comment_count property not found".to_string()))?; 46 - let share_count_prop = schema.get_property_key_id("share_count") 47 - .ok_or_else(|| AppError::DatabaseError("share_count property not found".to_string()))?; 48 - let view_count_prop = schema.get_property_key_id("view_count") 49 - .ok_or_else(|| AppError::DatabaseError("view_count property not found".to_string()))?; 50 - let is_public_prop = schema.get_property_key_id("is_public") 51 - .ok_or_else(|| AppError::DatabaseError("is_public property not found".to_string()))?; 52 - let posted_rel = schema.get_relationship_type_id("POSTED") 53 - .ok_or_else(|| AppError::DatabaseError("POSTED relationship not found".to_string()))?; 29 + let mut schema = self.graph.schema().write(); 30 + let post_label = schema.get_or_create_label("Post"); 31 + let id_prop = schema.get_or_create_property_key("id"); 32 + let content_prop = schema.get_or_create_property_key("content"); 33 + let author_id_prop = schema.get_or_create_property_key("author_id"); 34 + let created_at_prop = schema.get_or_create_property_key("created_at"); 35 + let updated_at_prop = schema.get_or_create_property_key("updated_at"); 36 + let like_count_prop = schema.get_or_create_property_key("like_count"); 37 + let comment_count_prop = schema.get_or_create_property_key("comment_count"); 38 + let share_count_prop = schema.get_or_create_property_key("share_count"); 39 + let view_count_prop = schema.get_or_create_property_key("view_count"); 40 + let is_public_prop = schema.get_or_create_property_key("is_public"); 41 + let posted_rel = schema.get_or_create_relationship_type("POSTED"); 54 42 drop(schema); 55 43 56 44 let now = Utc::now(); ··· 105 93 .ok_or(AppError::PostNotFound)?; 106 94 107 95 // Increment view count 108 - let schema = self.graph.schema().read(); 109 - let view_count_prop = schema.get_property_key_id("view_count") 110 - .ok_or_else(|| AppError::DatabaseError("view_count property not found".to_string()))?; 96 + let mut schema = self.graph.schema().write(); 97 + let view_count_prop = schema.get_or_create_property_key("view_count"); 111 98 drop(schema); 112 99 113 100 self.graph.update_node(node_id, |node| { 114 101 let current_views = node.properties.get(&view_count_prop) 115 102 .and_then(|v| match v { 116 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 103 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 117 104 _ => None, 118 105 }) 119 106 .unwrap_or(0); ··· 128 115 let node_id = self.find_post_node_by_id(post_id).await? 129 116 .ok_or(AppError::PostNotFound)?; 130 117 131 - let schema = self.graph.schema().read(); 132 - let updated_at_prop = schema.get_property_key_id("updated_at") 133 - .ok_or_else(|| AppError::DatabaseError("updated_at property not found".to_string()))?; 118 + let mut schema = self.graph.schema().write(); 119 + let updated_at_prop = schema.get_or_create_property_key("updated_at"); 134 120 drop(schema); 135 121 136 122 self.graph.update_node(node_id, |node| { ··· 174 160 let post_node = self.find_post_node_by_id(post_id).await? 175 161 .ok_or(AppError::PostNotFound)?; 176 162 177 - let schema = self.graph.schema().read(); 178 - let likes_rel = schema.get_relationship_type_id("LIKES") 179 - .ok_or_else(|| AppError::DatabaseError("LIKES relationship not found".to_string()))?; 180 - let like_count_prop = schema.get_property_key_id("like_count") 181 - .ok_or_else(|| AppError::DatabaseError("like_count property not found".to_string()))?; 163 + let mut schema = self.graph.schema().write(); 164 + let likes_rel = schema.get_or_create_relationship_type("LIKES"); 165 + let like_count_prop = schema.get_or_create_property_key("like_count"); 182 166 drop(schema); 183 167 184 168 // Check if already liked ··· 194 178 self.graph.update_node(post_node, |node| { 195 179 let current_likes = node.properties.get(&like_count_prop) 196 180 .and_then(|v| match v { 197 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 181 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 198 182 _ => None, 199 183 }) 200 184 .unwrap_or(0); ··· 213 197 .ok_or(AppError::PostNotFound)?; 214 198 215 199 let schema = self.graph.schema().read(); 216 - let likes_rel = schema.get_relationship_type_id("LIKES") 200 + let likes_rel = schema.relationship_types.get("LIKES").copied() 217 201 .ok_or_else(|| AppError::DatabaseError("LIKES relationship not found".to_string()))?; 218 - let like_count_prop = schema.get_property_key_id("like_count") 202 + let like_count_prop = schema.property_keys.get("like_count").copied() 219 203 .ok_or_else(|| AppError::DatabaseError("like_count property not found".to_string()))?; 220 204 drop(schema); 221 205 ··· 230 214 self.graph.update_node(post_node, |node| { 231 215 let current_likes = node.properties.get(&like_count_prop) 232 216 .and_then(|v| match v { 233 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 217 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 234 218 _ => None, 235 219 }) 236 220 .unwrap_or(0); ··· 251 235 let node_id = self.graph.create_node(); 252 236 253 237 let schema = self.graph.schema().read(); 254 - let comment_label = schema.get_label_id("Comment") 238 + let comment_label = schema.labels.get("Comment").copied() 255 239 .ok_or_else(|| AppError::DatabaseError("Comment label not found".to_string()))?; 256 - let commented_on_rel = schema.get_relationship_type_id("COMMENTED_ON") 240 + let commented_on_rel = schema.relationship_types.get("COMMENTED_ON").copied() 257 241 .ok_or_else(|| AppError::DatabaseError("COMMENTED_ON relationship not found".to_string()))?; 258 - let comment_count_prop = schema.get_property_key_id("comment_count") 242 + let comment_count_prop = schema.property_keys.get("comment_count").copied() 259 243 .ok_or_else(|| AppError::DatabaseError("comment_count property not found".to_string()))?; 260 244 drop(schema); 261 245 ··· 271 255 { 272 256 node.properties.insert(id_prop, gigabrain::core::PropertyValue::String(comment_id.clone())); 273 257 } 274 - if let Some(content_prop) = schema.get_property_key_id("content") { 258 + if let Some(content_prop) = schema.property_keys.get("content").copied() { 275 259 node.properties.insert(content_prop, gigabrain::core::PropertyValue::String(request.content.clone())); 276 260 } 277 - if let Some(author_id_prop) = schema.get_property_key_id("author_id") { 261 + if let Some(author_id_prop) = schema.property_keys.get("author_id").copied() { 278 262 node.properties.insert(author_id_prop, gigabrain::core::PropertyValue::String(request.author_id.clone())); 279 263 } 280 - if let Some(created_at_prop) = schema.get_property_key_id("created_at") { 264 + if let Some(created_at_prop) = schema.property_keys.get("created_at").copied() { 281 265 node.properties.insert(created_at_prop, gigabrain::core::PropertyValue::String(now.to_rfc3339())); 282 266 } 283 267 }).map_err(|e| AppError::DatabaseError(e.to_string()))?; ··· 293 277 self.graph.update_node(post_node, |node| { 294 278 let current_comments = node.properties.get(&comment_count_prop) 295 279 .and_then(|v| match v { 296 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 280 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 297 281 _ => None, 298 282 }) 299 283 .unwrap_or(0); ··· 323 307 let share_node = self.graph.create_node(); 324 308 325 309 let schema = self.graph.schema().read(); 326 - let post_label = schema.get_label_id("Post") 310 + let post_label = schema.labels.get("Post").copied() 327 311 .ok_or_else(|| AppError::DatabaseError("Post label not found".to_string()))?; 328 - let share_label = schema.get_label_id("Share") 312 + let share_label = schema.labels.get("Share").copied() 329 313 .ok_or_else(|| AppError::DatabaseError("Share label not found".to_string()))?; 330 - let shared_rel = schema.get_relationship_type_id("SHARED") 314 + let shared_rel = schema.relationship_types.get("SHARED").copied() 331 315 .ok_or_else(|| AppError::DatabaseError("SHARED relationship not found".to_string()))?; 332 - let posted_rel = schema.get_relationship_type_id("POSTED") 316 + let posted_rel = schema.relationship_types.get("POSTED").copied() 333 317 .ok_or_else(|| AppError::DatabaseError("POSTED relationship not found".to_string()))?; 334 - let share_count_prop = schema.get_property_key_id("share_count") 318 + let share_count_prop = schema.property_keys.get("share_count").copied() 335 319 .ok_or_else(|| AppError::DatabaseError("share_count property not found".to_string()))?; 336 320 drop(schema); 337 321 ··· 352 336 { 353 337 node.properties.insert(id_prop, gigabrain::core::PropertyValue::String(share_id.clone())); 354 338 } 355 - if let Some(content_prop) = schema.get_property_key_id("content") { 339 + if let Some(content_prop) = schema.property_keys.get("content").copied() { 356 340 node.properties.insert(content_prop, gigabrain::core::PropertyValue::String(share_content.clone())); 357 341 } 358 - if let Some(author_id_prop) = schema.get_property_key_id("author_id") { 342 + if let Some(author_id_prop) = schema.property_keys.get("author_id").copied() { 359 343 node.properties.insert(author_id_prop, gigabrain::core::PropertyValue::String(user_id.to_string())); 360 344 } 361 - if let Some(created_at_prop) = schema.get_property_key_id("created_at") { 345 + if let Some(created_at_prop) = schema.property_keys.get("created_at").copied() { 362 346 node.properties.insert(created_at_prop, gigabrain::core::PropertyValue::String(now.to_rfc3339())); 363 347 } 364 - if let Some(updated_at_prop) = schema.get_property_key_id("updated_at") { 348 + if let Some(updated_at_prop) = schema.property_keys.get("updated_at").copied() { 365 349 node.properties.insert(updated_at_prop, gigabrain::core::PropertyValue::String(now.to_rfc3339())); 366 350 } 367 - if let Some(like_count_prop) = schema.get_property_key_id("like_count") { 351 + if let Some(like_count_prop) = schema.property_keys.get("like_count").copied() { 368 352 node.properties.insert(like_count_prop, gigabrain::core::PropertyValue::Integer(0)); 369 353 } 370 - if let Some(comment_count_prop) = schema.get_property_key_id("comment_count") { 354 + if let Some(comment_count_prop) = schema.property_keys.get("comment_count").copied() { 371 355 node.properties.insert(comment_count_prop, gigabrain::core::PropertyValue::Integer(0)); 372 356 } 373 - if let Some(share_count_prop) = schema.get_property_key_id("share_count") { 357 + if let Some(share_count_prop) = schema.property_keys.get("share_count").copied() { 374 358 node.properties.insert(share_count_prop, gigabrain::core::PropertyValue::Integer(0)); 375 359 } 376 - if let Some(view_count_prop) = schema.get_property_key_id("view_count") { 360 + if let Some(view_count_prop) = schema.property_keys.get("view_count").copied() { 377 361 node.properties.insert(view_count_prop, gigabrain::core::PropertyValue::Integer(0)); 378 362 } 379 - if let Some(is_public_prop) = schema.get_property_key_id("is_public") { 363 + if let Some(is_public_prop) = schema.property_keys.get("is_public").copied() { 380 364 node.properties.insert(is_public_prop, gigabrain::core::PropertyValue::Boolean(true)); 381 365 } 382 366 }).map_err(|e| AppError::DatabaseError(e.to_string()))?; ··· 391 375 self.graph.update_node(original_post_node, |node| { 392 376 let current_shares = node.properties.get(&share_count_prop) 393 377 .and_then(|v| match v { 394 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 378 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 395 379 _ => None, 396 380 }) 397 381 .unwrap_or(0); ··· 421 405 .ok_or(AppError::UserNotFound)?; 422 406 423 407 let schema = self.graph.schema().read(); 424 - let posted_rel = schema.get_relationship_type_id("POSTED") 408 + let posted_rel = schema.relationship_types.get("POSTED").copied() 425 409 .ok_or_else(|| AppError::DatabaseError("POSTED relationship not found".to_string()))?; 426 410 drop(schema); 427 411 ··· 460 444 let limit = params.limit.unwrap_or(20); 461 445 462 446 let schema = self.graph.schema().read(); 463 - let post_label = schema.get_label_id("Post") 447 + let post_label = schema.labels.get("Post").copied() 464 448 .ok_or_else(|| AppError::DatabaseError("Post label not found".to_string()))?; 465 - let like_count_prop = schema.get_property_key_id("like_count") 449 + let like_count_prop = schema.property_keys.get("like_count").copied() 466 450 .ok_or_else(|| AppError::DatabaseError("like_count property not found".to_string()))?; 467 451 drop(schema); 468 452 ··· 474 458 if node.has_label(post_label) { 475 459 let likes = node.properties.get(&like_count_prop) 476 460 .and_then(|v| match v { 477 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 461 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 478 462 _ => None, 479 463 }) 480 464 .unwrap_or(0); ··· 545 529 // Helper methods 546 530 async fn find_post_node_by_id(&self, post_id: &str) -> Result<Option<NodeId>, AppError> { 547 531 let schema = self.graph.schema().read(); 548 - let post_label = schema.get_label_id("Post") 532 + let post_label = schema.labels.get("Post").copied() 549 533 .ok_or_else(|| AppError::DatabaseError("Post label not found".to_string()))?; 550 - let id_prop = schema.get_property_key_id("id") 534 + let id_prop = schema.property_keys.get("id").copied() 551 535 .ok_or_else(|| AppError::DatabaseError("id property not found".to_string()))?; 552 536 drop(schema); 553 537 ··· 570 554 571 555 async fn find_user_node_by_id(&self, user_id: &str) -> Result<Option<NodeId>, AppError> { 572 556 let schema = self.graph.schema().read(); 573 - let user_label = schema.get_label_id("User") 557 + let user_label = schema.labels.get("User").copied() 574 558 .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 575 - let id_prop = schema.get_property_key_id("id") 559 + let id_prop = schema.property_keys.get("id").copied() 576 560 .ok_or_else(|| AppError::DatabaseError("id property not found".to_string()))?; 577 561 drop(schema); 578 562 ··· 649 633 async fn create_or_link_hashtag(&self, post_node: NodeId, hashtag: &str) -> Result<(), AppError> { 650 634 // Find or create hashtag node 651 635 let schema = self.graph.schema().read(); 652 - let hashtag_label = schema.get_label_id("Hashtag") 636 + let hashtag_label = schema.labels.get("Hashtag").copied() 653 637 .ok_or_else(|| AppError::DatabaseError("Hashtag label not found".to_string()))?; 654 - let tagged_with_rel = schema.get_relationship_type_id("TAGGED_WITH") 638 + let tagged_with_rel = schema.relationship_types.get("TAGGED_WITH").copied() 655 639 .ok_or_else(|| AppError::DatabaseError("TAGGED_WITH relationship not found".to_string()))?; 656 640 drop(schema); 657 641 ··· 668 652 { 669 653 node.properties.insert(id_prop, gigabrain::core::PropertyValue::String(hashtag.to_string())); 670 654 } 671 - if let Some(content_prop) = schema.get_property_key_id("content") { 655 + if let Some(content_prop) = schema.property_keys.get("content").copied() { 672 656 node.properties.insert(content_prop, gigabrain::core::PropertyValue::String(hashtag.to_string())); 673 657 } 674 658 }).map_err(|e| AppError::DatabaseError(e.to_string()))?; ··· 682 666 683 667 // Property helper methods (same as user_service) 684 668 fn get_string_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Result<String, AppError> { 685 - let prop_id = schema.get_property_key_id(key) 669 + let prop_id = schema.property_keys.get(key).copied() 686 670 .ok_or_else(|| AppError::DatabaseError(format!("{} property not found", key)))?; 687 671 688 672 match node.properties.get(&prop_id) { ··· 692 676 } 693 677 694 678 fn get_int_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<i64> { 695 - schema.get_property_key_id(key) 679 + schema.property_keys.get(key).copied() 696 680 .and_then(|prop_id| node.properties.get(&prop_id)) 697 681 .and_then(|v| match v { 698 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 682 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 699 683 _ => None, 700 684 }) 701 685 } 702 686 703 687 fn get_bool_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<bool> { 704 - schema.get_property_key_id(key) 688 + schema.property_keys.get(key).copied() 705 689 .and_then(|prop_id| node.properties.get(&prop_id)) 706 690 .and_then(|v| match v { 707 - gigabrain::core::PropertyValue::Boolean(b) => Some(b), 691 + gigabrain::core::PropertyValue::Boolean(b) => Some(*b), 708 692 _ => None, 709 693 }) 710 694 } 711 695 712 696 fn get_datetime_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Result<chrono::DateTime<chrono::Utc>, AppError> { 713 - let prop_id = schema.get_property_key_id(key) 697 + let prop_id = schema.property_keys.get(key).copied() 714 698 .ok_or_else(|| AppError::DatabaseError(format!("{} property not found", key)))?; 715 699 716 700 match node.properties.get(&prop_id) {
+22 -22
examples/social-network/src/services/recommendation_service.rs
··· 145 145 146 146 // Get all hashtags and their usage 147 147 let schema = self.graph.schema().read(); 148 - let hashtag_label = schema.get_label_id("Hashtag") 148 + let hashtag_label = schema.labels.get("Hashtag").copied() 149 149 .ok_or_else(|| AppError::DatabaseError("Hashtag label not found".to_string()))?; 150 - let tagged_with_rel = schema.get_relationship_type_id("TAGGED_WITH") 150 + let tagged_with_rel = schema.relationship_types.get("TAGGED_WITH").copied() 151 151 .ok_or_else(|| AppError::DatabaseError("TAGGED_WITH relationship not found".to_string()))?; 152 152 drop(schema); 153 153 ··· 252 252 253 253 async fn get_popular_users(&self, user_id: &str) -> Result<Vec<User>, AppError> { 254 254 let schema = self.graph.schema().read(); 255 - let user_label = schema.get_label_id("User") 255 + let user_label = schema.labels.get("User").copied() 256 256 .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 257 - let follower_count_prop = schema.get_property_key_id("follower_count") 257 + let follower_count_prop = schema.property_keys.get("follower_count").copied() 258 258 .ok_or_else(|| AppError::DatabaseError("follower_count property not found".to_string()))?; 259 259 drop(schema); 260 260 ··· 266 266 if node.has_label(user_label) { 267 267 let followers = node.properties.get(&follower_count_prop) 268 268 .and_then(|v| match v { 269 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 269 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 270 270 _ => None, 271 271 }) 272 272 .unwrap_or(0); ··· 328 328 329 329 async fn get_trending_posts(&self) -> Result<Vec<Post>, AppError> { 330 330 let schema = self.graph.schema().read(); 331 - let post_label = schema.get_label_id("Post") 331 + let post_label = schema.labels.get("Post").copied() 332 332 .ok_or_else(|| AppError::DatabaseError("Post label not found".to_string()))?; 333 - let like_count_prop = schema.get_property_key_id("like_count") 333 + let like_count_prop = schema.property_keys.get("like_count").copied() 334 334 .ok_or_else(|| AppError::DatabaseError("like_count property not found".to_string()))?; 335 335 drop(schema); 336 336 ··· 342 342 if node.has_label(post_label) { 343 343 let likes = node.properties.get(&like_count_prop) 344 344 .and_then(|v| match v { 345 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 345 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 346 346 _ => None, 347 347 }) 348 348 .unwrap_or(0); ··· 410 410 .ok_or(AppError::UserNotFound)?; 411 411 412 412 let schema = self.graph.schema().read(); 413 - let follows_rel = schema.get_relationship_type_id("FOLLOWS") 413 + let follows_rel = schema.relationship_types.get("FOLLOWS").copied() 414 414 .ok_or_else(|| AppError::DatabaseError("FOLLOWS relationship not found".to_string()))?; 415 415 drop(schema); 416 416 ··· 445 445 .ok_or(AppError::UserNotFound)?; 446 446 447 447 let schema = self.graph.schema().read(); 448 - let posted_rel = schema.get_relationship_type_id("POSTED") 448 + let posted_rel = schema.relationship_types.get("POSTED").copied() 449 449 .ok_or_else(|| AppError::DatabaseError("POSTED relationship not found".to_string()))?; 450 450 drop(schema); 451 451 ··· 463 463 464 464 async fn get_all_posts(&self) -> Result<Vec<Post>, AppError> { 465 465 let schema = self.graph.schema().read(); 466 - let post_label = schema.get_label_id("Post") 466 + let post_label = schema.labels.get("Post").copied() 467 467 .ok_or_else(|| AppError::DatabaseError("Post label not found".to_string()))?; 468 468 drop(schema); 469 469 ··· 511 511 .ok_or(AppError::DatabaseError("Hashtag node not found".to_string()))?; 512 512 513 513 let schema = self.graph.schema().read(); 514 - let content_prop = schema.get_property_key_id("content") 514 + let content_prop = schema.property_keys.get("content").copied() 515 515 .ok_or_else(|| AppError::DatabaseError("content property not found".to_string()))?; 516 516 drop(schema); 517 517 ··· 524 524 // Standard helper methods 525 525 async fn find_user_node_by_id(&self, user_id: &str) -> Result<Option<NodeId>, AppError> { 526 526 let schema = self.graph.schema().read(); 527 - let user_label = schema.get_label_id("User") 527 + let user_label = schema.labels.get("User").copied() 528 528 .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 529 - let id_prop = schema.get_property_key_id("id") 529 + let id_prop = schema.property_keys.get("id").copied() 530 530 .ok_or_else(|| AppError::DatabaseError("id property not found".to_string()))?; 531 531 drop(schema); 532 532 ··· 639 639 640 640 // Property helper methods 641 641 fn get_string_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Result<String, AppError> { 642 - let prop_id = schema.get_property_key_id(key) 642 + let prop_id = schema.property_keys.get(key).copied() 643 643 .ok_or_else(|| AppError::DatabaseError(format!("{} property not found", key)))?; 644 644 645 645 match node.properties.get(&prop_id) { ··· 649 649 } 650 650 651 651 fn get_optional_string_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<String> { 652 - schema.get_property_key_id(key) 652 + schema.property_keys.get(key).copied() 653 653 .and_then(|prop_id| node.properties.get(&prop_id)) 654 654 .and_then(|v| match v { 655 655 gigabrain::core::PropertyValue::String(s) => Some(s.clone()), ··· 658 658 } 659 659 660 660 fn get_int_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<i64> { 661 - schema.get_property_key_id(key) 661 + schema.property_keys.get(key).copied() 662 662 .and_then(|prop_id| node.properties.get(&prop_id)) 663 663 .and_then(|v| match v { 664 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 664 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 665 665 _ => None, 666 666 }) 667 667 } 668 668 669 669 fn get_bool_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<bool> { 670 - schema.get_property_key_id(key) 670 + schema.property_keys.get(key).copied() 671 671 .and_then(|prop_id| node.properties.get(&prop_id)) 672 672 .and_then(|v| match v { 673 - gigabrain::core::PropertyValue::Boolean(b) => Some(b), 673 + gigabrain::core::PropertyValue::Boolean(b) => Some(*b), 674 674 _ => None, 675 675 }) 676 676 } 677 677 678 678 fn get_datetime_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Result<chrono::DateTime<chrono::Utc>, AppError> { 679 - let prop_id = schema.get_property_key_id(key) 679 + let prop_id = schema.property_keys.get(key).copied() 680 680 .ok_or_else(|| AppError::DatabaseError(format!("{} property not found", key)))?; 681 681 682 682 match node.properties.get(&prop_id) { ··· 690 690 } 691 691 692 692 fn get_optional_datetime_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<chrono::DateTime<chrono::Utc>> { 693 - schema.get_property_key_id(key) 693 + schema.property_keys.get(key).copied() 694 694 .and_then(|prop_id| node.properties.get(&prop_id)) 695 695 .and_then(|v| match v { 696 696 gigabrain::core::PropertyValue::String(s) => {
+26 -26
examples/social-network/src/services/social_service.rs
··· 27 27 .ok_or(AppError::UserNotFound)?; 28 28 29 29 let schema = self.graph.schema().read(); 30 - let follows_rel = schema.get_relationship_type_id("FOLLOWS") 30 + let follows_rel = schema.relationship_types.get("FOLLOWS").copied() 31 31 .ok_or_else(|| AppError::DatabaseError("FOLLOWS relationship not found".to_string()))?; 32 - let following_count_prop = schema.get_property_key_id("following_count") 32 + let following_count_prop = schema.property_keys.get("following_count").copied() 33 33 .ok_or_else(|| AppError::DatabaseError("following_count property not found".to_string()))?; 34 - let follower_count_prop = schema.get_property_key_id("follower_count") 34 + let follower_count_prop = schema.property_keys.get("follower_count").copied() 35 35 .ok_or_else(|| AppError::DatabaseError("follower_count property not found".to_string()))?; 36 36 drop(schema); 37 37 ··· 48 48 self.graph.update_node(follower_node, |node| { 49 49 let current_count = node.properties.get(&following_count_prop) 50 50 .and_then(|v| match v { 51 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 51 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 52 52 _ => None, 53 53 }) 54 54 .unwrap_or(0); ··· 60 60 self.graph.update_node(followee_node, |node| { 61 61 let current_count = node.properties.get(&follower_count_prop) 62 62 .and_then(|v| match v { 63 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 63 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 64 64 _ => None, 65 65 }) 66 66 .unwrap_or(0); ··· 81 81 .ok_or(AppError::UserNotFound)?; 82 82 83 83 let schema = self.graph.schema().read(); 84 - let follows_rel = schema.get_relationship_type_id("FOLLOWS") 84 + let follows_rel = schema.relationship_types.get("FOLLOWS").copied() 85 85 .ok_or_else(|| AppError::DatabaseError("FOLLOWS relationship not found".to_string()))?; 86 - let following_count_prop = schema.get_property_key_id("following_count") 86 + let following_count_prop = schema.property_keys.get("following_count").copied() 87 87 .ok_or_else(|| AppError::DatabaseError("following_count property not found".to_string()))?; 88 - let follower_count_prop = schema.get_property_key_id("follower_count") 88 + let follower_count_prop = schema.property_keys.get("follower_count").copied() 89 89 .ok_or_else(|| AppError::DatabaseError("follower_count property not found".to_string()))?; 90 90 drop(schema); 91 91 ··· 100 100 self.graph.update_node(follower_node, |node| { 101 101 let current_count = node.properties.get(&following_count_prop) 102 102 .and_then(|v| match v { 103 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 103 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 104 104 _ => None, 105 105 }) 106 106 .unwrap_or(0); ··· 112 112 self.graph.update_node(followee_node, |node| { 113 113 let current_count = node.properties.get(&follower_count_prop) 114 114 .and_then(|v| match v { 115 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 115 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 116 116 _ => None, 117 117 }) 118 118 .unwrap_or(0); ··· 133 133 .ok_or(AppError::UserNotFound)?; 134 134 135 135 let schema = self.graph.schema().read(); 136 - let follows_rel = schema.get_relationship_type_id("FOLLOWS") 136 + let follows_rel = schema.relationship_types.get("FOLLOWS").copied() 137 137 .ok_or_else(|| AppError::DatabaseError("FOLLOWS relationship not found".to_string()))?; 138 138 drop(schema); 139 139 ··· 158 158 .ok_or(AppError::UserNotFound)?; 159 159 160 160 let schema = self.graph.schema().read(); 161 - let follows_rel = schema.get_relationship_type_id("FOLLOWS") 161 + let follows_rel = schema.relationship_types.get("FOLLOWS").copied() 162 162 .ok_or_else(|| AppError::DatabaseError("FOLLOWS relationship not found".to_string()))?; 163 163 drop(schema); 164 164 ··· 213 213 .ok_or(AppError::UserNotFound)?; 214 214 215 215 let schema = self.graph.schema().read(); 216 - let follows_rel = schema.get_relationship_type_id("FOLLOWS") 216 + let follows_rel = schema.relationship_types.get("FOLLOWS").copied() 217 217 .ok_or_else(|| AppError::DatabaseError("FOLLOWS relationship not found".to_string()))?; 218 218 drop(schema); 219 219 ··· 225 225 226 226 pub async fn get_network_analytics(&self) -> Result<NetworkAnalytics, AppError> { 227 227 let schema = self.graph.schema().read(); 228 - let user_label = schema.get_label_id("User") 228 + let user_label = schema.labels.get("User").copied() 229 229 .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 230 - let post_label = schema.get_label_id("Post") 230 + let post_label = schema.labels.get("Post").copied() 231 231 .ok_or_else(|| AppError::DatabaseError("Post label not found".to_string()))?; 232 - let follows_rel = schema.get_relationship_type_id("FOLLOWS") 232 + let follows_rel = schema.relationship_types.get("FOLLOWS").copied() 233 233 .ok_or_else(|| AppError::DatabaseError("FOLLOWS relationship not found".to_string()))?; 234 234 drop(schema); 235 235 ··· 321 321 // Helper methods 322 322 async fn find_user_node_by_id(&self, user_id: &str) -> Result<Option<NodeId>, AppError> { 323 323 let schema = self.graph.schema().read(); 324 - let user_label = schema.get_label_id("User") 324 + let user_label = schema.labels.get("User").copied() 325 325 .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 326 - let id_prop = schema.get_property_key_id("id") 326 + let id_prop = schema.property_keys.get("id").copied() 327 327 .ok_or_else(|| AppError::DatabaseError("id property not found".to_string()))?; 328 328 drop(schema); 329 329 ··· 383 383 384 384 // Property helper methods (same as other services) 385 385 fn get_string_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Result<String, AppError> { 386 - let prop_id = schema.get_property_key_id(key) 386 + let prop_id = schema.property_keys.get(key).copied() 387 387 .ok_or_else(|| AppError::DatabaseError(format!("{} property not found", key)))?; 388 388 389 389 match node.properties.get(&prop_id) { ··· 393 393 } 394 394 395 395 fn get_optional_string_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<String> { 396 - schema.get_property_key_id(key) 396 + schema.property_keys.get(key).copied() 397 397 .and_then(|prop_id| node.properties.get(&prop_id)) 398 398 .and_then(|v| match v { 399 399 gigabrain::core::PropertyValue::String(s) => Some(s.clone()), ··· 402 402 } 403 403 404 404 fn get_int_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<i64> { 405 - schema.get_property_key_id(key) 405 + schema.property_keys.get(key).copied() 406 406 .and_then(|prop_id| node.properties.get(&prop_id)) 407 407 .and_then(|v| match v { 408 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 408 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 409 409 _ => None, 410 410 }) 411 411 } 412 412 413 413 fn get_bool_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<bool> { 414 - schema.get_property_key_id(key) 414 + schema.property_keys.get(key).copied() 415 415 .and_then(|prop_id| node.properties.get(&prop_id)) 416 416 .and_then(|v| match v { 417 - gigabrain::core::PropertyValue::Boolean(b) => Some(b), 417 + gigabrain::core::PropertyValue::Boolean(b) => Some(*b), 418 418 _ => None, 419 419 }) 420 420 } 421 421 422 422 fn get_datetime_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Result<chrono::DateTime<chrono::Utc>, AppError> { 423 - let prop_id = schema.get_property_key_id(key) 423 + let prop_id = schema.property_keys.get(key).copied() 424 424 .ok_or_else(|| AppError::DatabaseError(format!("{} property not found", key)))?; 425 425 426 426 match node.properties.get(&prop_id) { ··· 434 434 } 435 435 436 436 fn get_optional_datetime_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<chrono::DateTime<chrono::Utc>> { 437 - schema.get_property_key_id(key) 437 + schema.property_keys.get(key).copied() 438 438 .and_then(|prop_id| node.properties.get(&prop_id)) 439 439 .and_then(|v| match v { 440 440 gigabrain::core::PropertyValue::String(s) => {
+27 -36
examples/social-network/src/services/user_service.rs
··· 113 113 let node_id = self.find_user_node_by_id(user_id).await? 114 114 .ok_or(AppError::UserNotFound)?; 115 115 116 - let schema = self.graph.schema().read(); 117 - let updated_at_prop = schema.get_property_key_id("updated_at") 118 - .ok_or_else(|| AppError::DatabaseError("updated_at property not found".to_string()))?; 116 + let mut schema = self.graph.schema().write(); 117 + let updated_at_prop = schema.get_or_create_property_key("updated_at"); 119 118 drop(schema); 120 119 121 120 self.graph.update_node(node_id, |node| { ··· 167 166 let query = params.q.to_lowercase(); 168 167 let limit = params.limit.unwrap_or(20); 169 168 170 - let schema = self.graph.schema().read(); 171 - let user_label = schema.get_label_id("User") 172 - .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 173 - let username_prop = schema.get_property_key_id("username") 174 - .ok_or_else(|| AppError::DatabaseError("username property not found".to_string()))?; 169 + let mut schema = self.graph.schema().write(); 170 + let user_label = schema.get_or_create_label("User"); 171 + let username_prop = schema.get_or_create_property_key("username"); 175 172 drop(schema); 176 173 177 174 let mut results = Vec::new(); ··· 202 199 let node = self.graph.get_node(node_id) 203 200 .ok_or(AppError::InvalidCredentials)?; 204 201 205 - let schema = self.graph.schema().read(); 206 - let password_hash_prop = schema.get_property_key_id("password_hash") 207 - .ok_or_else(|| AppError::DatabaseError("password_hash property not found".to_string()))?; 208 - let last_login_prop = schema.get_property_key_id("last_login") 209 - .ok_or_else(|| AppError::DatabaseError("last_login property not found".to_string()))?; 202 + let mut schema = self.graph.schema().write(); 203 + let password_hash_prop = schema.get_or_create_property_key("password_hash"); 204 + let last_login_prop = schema.get_or_create_property_key("last_login"); 210 205 drop(schema); 211 206 212 207 let stored_hash = match node.properties.get(&password_hash_prop) { ··· 257 252 258 253 // Helper methods 259 254 async fn find_user_node_by_id(&self, user_id: &str) -> Result<Option<NodeId>, AppError> { 260 - let schema = self.graph.schema().read(); 261 - let user_label = schema.get_label_id("User") 262 - .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 263 - let id_prop = schema.get_property_key_id("id") 264 - .ok_or_else(|| AppError::DatabaseError("id property not found".to_string()))?; 255 + let mut schema = self.graph.schema().write(); 256 + let user_label = schema.get_or_create_label("User"); 257 + let id_prop = schema.get_or_create_property_key("id"); 265 258 drop(schema); 266 259 267 260 let nodes = self.graph.get_all_nodes(); ··· 282 275 } 283 276 284 277 async fn find_user_node_by_username(&self, username: &str) -> Result<Option<NodeId>, AppError> { 285 - let schema = self.graph.schema().read(); 286 - let user_label = schema.get_label_id("User") 287 - .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 288 - let username_prop = schema.get_property_key_id("username") 289 - .ok_or_else(|| AppError::DatabaseError("username property not found".to_string()))?; 278 + let mut schema = self.graph.schema().write(); 279 + let user_label = schema.get_or_create_label("User"); 280 + let username_prop = schema.get_or_create_property_key("username"); 290 281 drop(schema); 291 282 292 283 let nodes = self.graph.get_all_nodes(); ··· 315 306 } 316 307 317 308 async fn find_user_by_email(&self, email: &str) -> Result<Option<User>, AppError> { 318 - let schema = self.graph.schema().read(); 319 - let user_label = schema.get_label_id("User") 320 - .ok_or_else(|| AppError::DatabaseError("User label not found".to_string()))?; 321 - let email_prop = schema.get_property_key_id("email") 322 - .ok_or_else(|| AppError::DatabaseError("email property not found".to_string()))?; 309 + let mut schema = self.graph.schema().write(); 310 + let user_label = schema.get_or_create_label("User"); 311 + let email_prop = schema.get_or_create_property_key("email"); 323 312 drop(schema); 324 313 325 314 let nodes = self.graph.get_all_nodes(); ··· 377 366 } 378 367 379 368 fn get_string_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Result<String, AppError> { 380 - let prop_id = schema.get_property_key_id(key) 369 + // For read operations, we need to find the property key ID differently 370 + // Since we can't modify schema in read context, we'll search through existing keys 371 + let prop_id = schema.property_keys.get(key).copied() 381 372 .ok_or_else(|| AppError::DatabaseError(format!("{} property not found", key)))?; 382 373 383 374 match node.properties.get(&prop_id) { ··· 387 378 } 388 379 389 380 fn get_optional_string_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<String> { 390 - schema.get_property_key_id(key) 381 + schema.property_keys.get(key).copied() 391 382 .and_then(|prop_id| node.properties.get(&prop_id)) 392 383 .and_then(|v| match v { 393 384 gigabrain::core::PropertyValue::String(s) => Some(s.clone()), ··· 396 387 } 397 388 398 389 fn get_int_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<i64> { 399 - schema.get_property_key_id(key) 390 + schema.property_keys.get(key).copied() 400 391 .and_then(|prop_id| node.properties.get(&prop_id)) 401 392 .and_then(|v| match v { 402 - gigabrain::core::PropertyValue::Integer(i) => Some(i), 393 + gigabrain::core::PropertyValue::Integer(i) => Some(*i), 403 394 _ => None, 404 395 }) 405 396 } 406 397 407 398 fn get_bool_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<bool> { 408 - schema.get_property_key_id(key) 399 + schema.property_keys.get(key).copied() 409 400 .and_then(|prop_id| node.properties.get(&prop_id)) 410 401 .and_then(|v| match v { 411 - gigabrain::core::PropertyValue::Boolean(b) => Some(b), 402 + gigabrain::core::PropertyValue::Boolean(b) => Some(*b), 412 403 _ => None, 413 404 }) 414 405 } 415 406 416 407 fn get_datetime_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Result<DateTime<Utc>, AppError> { 417 - let prop_id = schema.get_property_key_id(key) 408 + let prop_id = schema.property_keys.get(key).copied() 418 409 .ok_or_else(|| AppError::DatabaseError(format!("{} property not found", key)))?; 419 410 420 411 match node.properties.get(&prop_id) { ··· 428 419 } 429 420 430 421 fn get_optional_datetime_property(&self, node: &gigabrain::core::Node, schema: &gigabrain::core::GraphSchema, key: &str) -> Option<DateTime<Utc>> { 431 - schema.get_property_key_id(key) 422 + schema.property_keys.get(key).copied() 432 423 .and_then(|prop_id| node.properties.get(&prop_id)) 433 424 .and_then(|v| match v { 434 425 gigabrain::core::PropertyValue::String(s) => {