| | @@ -72,11 +72,16 @@ |
| 72 | 72 | def query(self, cypher: str, params: dict[str, Any] | None = None) -> Any: |
| 73 | 73 | """Execute a raw Cypher query and return the result.""" |
| 74 | 74 | return self._graph.query(cypher, params or {}) |
| 75 | 75 | |
| 76 | 76 | def create_node(self, label: str, props: dict[str, Any]) -> None: |
| 77 | | - """Upsert a node by (label, name, file_path).""" |
| 77 | + """Upsert a node by (label, name[, file_path]).""" |
| 78 | + # Ensure merge key fields exist |
| 79 | + props.setdefault("name", "") |
| 80 | + props.setdefault("file_path", "") |
| 81 | + # Filter out None values — FalkorDB rejects them as params |
| 82 | + props = {k: ("" if v is None else v) for k, v in props.items()} |
| 78 | 83 | prop_str = ", ".join(f"n.{k} = ${k}" for k in props) |
| 79 | 84 | cypher = f"MERGE (n:{label} {{name: $name, file_path: $file_path}}) SET {prop_str}" |
| 80 | 85 | self.query(cypher, props) |
| 81 | 86 | |
| 82 | 87 | def create_edge( |
| | @@ -87,12 +92,12 @@ |
| 87 | 92 | to_label: str, |
| 88 | 93 | to_key: dict[str, Any], |
| 89 | 94 | props: dict[str, Any] | None = None, |
| 90 | 95 | ) -> None: |
| 91 | 96 | """Create a directed edge between two nodes, merging if it already exists.""" |
| 92 | | - from_match = " AND ".join(f"a.{k} = $from_{k}" for k in from_key) |
| 93 | | - to_match = " AND ".join(f"b.{k} = $to_{k}" for k in to_key) |
| 97 | + from_match = ", ".join(f"{k}: $from_{k}" for k in from_key) |
| 98 | + to_match = ", ".join(f"{k}: $to_{k}" for k in to_key) |
| 94 | 99 | prop_set = "" |
| 95 | 100 | if props: |
| 96 | 101 | prop_set = " SET " + ", ".join(f"r.{k} = $p_{k}" for k in props) |
| 97 | 102 | |
| 98 | 103 | cypher = ( |
| 99 | 104 | |