| 199 | |
| 200 | impl<'a> KgMutTxnT for WriteTxn<'a> { |
| 201 | fn upsert_kg_node(&mut self, node: &KgNode) -> PristineResult<()> { |
| 202 | let mut table = self.txn.open_table(KG_NODES)?; |
| 203 | let bytes = serde_json::to_vec(node).map_err(|e| PristineError::Serialization { |
| 204 | message: e.to_string(), |
| 205 | })?; |
| 206 | table.insert(node.id.as_str(), bytes.as_slice())?; |
| 207 | drop(table); |
| 208 | |
| 209 | // Update FTS index: add new tokens (duplicates are harmless |
| 210 | // in a multimap — the node_id appears multiple times but deduplication |
| 211 | // happens at query time via HashMap). |
| 212 | let mut fts_table = self.txn.open_multimap_table(KG_FTS)?; |
| 213 | let mut text = String::with_capacity(node.id.len() + node.label.len() + 64); |
| 214 | text.push_str(&node.id); |
| 215 | text.push(' '); |
| 216 | text.push_str(&node.label); |
| 217 | if let Some(ref summary) = node.summary { |
| 218 | text.push(' '); |
| 219 | text.push_str(summary); |
| 220 | } |
| 221 | for token in tokenize_for_fts(&text) { |
| 222 | fts_table.insert(token.as_str(), node.id.as_str())?; |
| 223 | } |
| 224 | |
| 225 | Ok(()) |
| 226 | } |
| 227 | |
| 228 | fn upsert_kg_edge(&mut self, edge: &KgEdge) -> PristineResult<()> { |
| 229 | let edge_key = encode_edge_key(&edge.from_id, &edge.to_id, &edge.kind); |