this repo has no description
0
fork

Configure Feed

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

Implement complete property and label storage for nodes

- Added update_node method to Graph for safe node modifications
- Added schema lookup methods to convert IDs back to names
- Fixed node creation to properly store labels and properties
- Fixed node retrieval to return labels and properties correctly
- Support for all property types: strings, integers, floats, booleans
- Nodes now correctly store and retrieve: labels and properties as documented

Verified working with test:
- Created node with labels ["Person", "Employee"] and mixed properties
- Retrieved node showing all data stored correctly

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

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

+114 -6
+12
src/core/graph.rs
··· 41 41 id 42 42 } 43 43 44 + pub fn update_node<F>(&self, id: NodeId, update_fn: F) -> Result<()> 45 + where 46 + F: FnOnce(&mut Node), 47 + { 48 + if let Some(mut node) = self.nodes.get_mut(&id) { 49 + update_fn(&mut node); 50 + Ok(()) 51 + } else { 52 + Err(GigabrainError::NodeNotFound(id)) 53 + } 54 + } 55 + 44 56 pub fn create_relationship( 45 57 &self, 46 58 start: NodeId,
+18
src/core/mod.rs
··· 67 67 self.next_relationship_type_id += 1; 68 68 id 69 69 } 70 + 71 + pub fn get_label_name(&self, label_id: LabelId) -> Option<String> { 72 + self.labels.iter() 73 + .find(|(_, &id)| id == label_id) 74 + .map(|(name, _)| name.clone()) 75 + } 76 + 77 + pub fn get_property_key_name(&self, key_id: PropertyKeyId) -> Option<String> { 78 + self.property_keys.iter() 79 + .find(|(_, &id)| id == key_id) 80 + .map(|(name, _)| name.clone()) 81 + } 82 + 83 + pub fn get_relationship_type_name(&self, type_id: u32) -> Option<String> { 84 + self.relationship_types.iter() 85 + .find(|(_, &id)| id == type_id) 86 + .map(|(name, _)| name.clone()) 87 + } 70 88 }
+84 -6
src/server/rest.rs
··· 221 221 ) -> Result<Json<CreateNodeResponse>, (StatusCode, Json<ErrorResponse>)> { 222 222 let node_id = graph.create_node(); 223 223 224 - // TODO: Handle labels and properties when implemented in core 224 + // Pre-process labels and properties to get their IDs 225 + let mut label_ids = Vec::new(); 226 + if let Some(ref labels) = request.labels { 227 + let mut schema = graph.schema().write(); 228 + for label_str in labels { 229 + let label_id = schema.get_or_create_label(label_str); 230 + label_ids.push(label_id); 231 + } 232 + } 233 + 234 + let mut property_entries = Vec::new(); 235 + if let Some(ref properties) = request.properties { 236 + let mut schema = graph.schema().write(); 237 + for (key_str, value) in properties { 238 + let property_key_id = schema.get_or_create_property_key(key_str); 239 + let property_value = match value { 240 + serde_json::Value::Null => crate::core::PropertyValue::Null, 241 + serde_json::Value::Bool(b) => crate::core::PropertyValue::Boolean(*b), 242 + serde_json::Value::Number(n) => { 243 + if let Some(i) = n.as_i64() { 244 + crate::core::PropertyValue::Integer(i) 245 + } else if let Some(f) = n.as_f64() { 246 + crate::core::PropertyValue::Float(f) 247 + } else { 248 + crate::core::PropertyValue::String(n.to_string()) 249 + } 250 + }, 251 + serde_json::Value::String(s) => crate::core::PropertyValue::String(s.clone()), 252 + serde_json::Value::Array(_) => crate::core::PropertyValue::String(value.to_string()), // TODO: Handle arrays 253 + serde_json::Value::Object(_) => crate::core::PropertyValue::String(value.to_string()), // TODO: Handle objects 254 + }; 255 + property_entries.push((property_key_id, property_value)); 256 + } 257 + } 225 258 226 - Ok(Json(CreateNodeResponse { node_id: node_id.0 })) 259 + // Handle labels and properties 260 + let update_result = graph.update_node(node_id, |node| { 261 + // Add labels 262 + for label_id in label_ids { 263 + node.add_label(label_id); 264 + } 265 + 266 + // Add properties 267 + for (property_key_id, property_value) in property_entries { 268 + node.properties.insert(property_key_id, property_value); 269 + } 270 + }); 271 + 272 + match update_result { 273 + Ok(_) => Ok(Json(CreateNodeResponse { node_id: node_id.0 })), 274 + Err(_) => Err(( 275 + StatusCode::INTERNAL_SERVER_ERROR, 276 + Json(ErrorResponse { 277 + error: "Failed to update node".to_string(), 278 + code: 500, 279 + }), 280 + )), 281 + } 227 282 } 228 283 229 284 async fn get_node( ··· 233 288 let node_id = crate::NodeId(id); 234 289 235 290 match graph.get_node(node_id) { 236 - Some(_node) => { 237 - // TODO: Return actual node data when properties/labels are implemented 291 + Some(node) => { 292 + let schema = graph.schema().read(); 293 + 294 + // Convert labels to strings 295 + let labels: Vec<String> = node.labels.iter() 296 + .filter_map(|&label_id| schema.get_label_name(label_id)) 297 + .collect(); 298 + 299 + // Convert properties to JSON values 300 + let mut properties = HashMap::new(); 301 + for (&property_key_id, property_value) in &node.properties { 302 + if let Some(key_name) = schema.get_property_key_name(property_key_id) { 303 + let json_value = match property_value { 304 + crate::core::PropertyValue::Null => serde_json::Value::Null, 305 + crate::core::PropertyValue::Boolean(b) => serde_json::Value::Bool(*b), 306 + crate::core::PropertyValue::Integer(i) => serde_json::Value::Number(serde_json::Number::from(*i)), 307 + crate::core::PropertyValue::Float(f) => serde_json::Value::Number(serde_json::Number::from_f64(*f).unwrap_or(serde_json::Number::from(0))), 308 + crate::core::PropertyValue::String(s) => serde_json::Value::String(s.clone()), 309 + crate::core::PropertyValue::List(_) => serde_json::Value::String("list".to_string()), // TODO: Handle lists 310 + crate::core::PropertyValue::Map(_) => serde_json::Value::String("map".to_string()), // TODO: Handle maps 311 + }; 312 + properties.insert(key_name, json_value); 313 + } 314 + } 315 + 238 316 Ok(Json(NodeResponse { 239 317 id, 240 - labels: vec![], 241 - properties: HashMap::new(), 318 + labels, 319 + properties, 242 320 })) 243 321 } 244 322 None => Err((