11from __future__ import annotations
22
3- from collections .abc import Iterable
4- from typing import Any , Optional , Union
3+ from typing import Optional , Union
54
65import neo4j .graph
76from neo4j import Result
@@ -22,8 +21,8 @@ def from_neo4j(
2221 Create a VisualizationGraph from a Neo4j Graph or Neo4j Result object.
2322
2423 All node and relationship properties will be included in the visualization graph.
25- If the property names are conflicting with those of `Node` and `Relationship` objects , they will be prefixed
26- with `__` .
24+ If the properties are named as the fields of the `Node` or `Relationship` classes , they will be included as
25+ top level fields of the respective objects. Otherwise, they will be included in the `properties` dictionary .
2726
2827 Parameters
2928 ----------
@@ -63,69 +62,64 @@ def from_neo4j(
6362
6463
6564def _map_node (node : neo4j .graph .Node , size_property : Optional [str ], caption_property : Optional [str ]) -> Node :
66- labels = sorted ([ label for label in node .labels ])
65+ top_level_fields = { "id" : node .element_id }
6766
6867 if size_property :
69- size = node .get (size_property )
70- else :
71- size = None
68+ top_level_fields ["size" ] = node .get (size_property )
7269
70+ labels = sorted ([label for label in node .labels ])
7371 if caption_property :
7472 if caption_property == "labels" :
7573 if len (labels ) > 0 :
76- caption = ":" .join ([label for label in labels ])
77- else :
78- caption = None
74+ top_level_fields ["caption" ] = ":" .join ([label for label in labels ])
7975 else :
80- caption = str (node .get (caption_property ))
76+ top_level_fields ["caption" ] = str (node .get (caption_property ))
77+
78+ properties = {}
79+ for prop , value in node .items ():
80+ if prop not in Node .model_fields .keys ():
81+ properties [prop ] = value
82+ continue
83+
84+ if prop in top_level_fields :
85+ properties [prop ] = value
86+ continue
8187
82- base_node_props = dict ( id = node . element_id , caption = caption , labels = labels , size = size )
88+ top_level_fields [ prop ] = value
8389
84- protected_props = base_node_props . keys ()
85- additional_node_props = { k : v for k , v in node . items ()}
86- additional_node_props = _rename_protected_props ( additional_node_props , protected_props )
90+ if "labels" in properties :
91+ properties [ "__labels" ] = properties [ "labels" ]
92+ properties [ "labels" ] = labels
8793
88- return Node (** base_node_props , ** additional_node_props )
94+ return Node (** top_level_fields , properties = properties )
8995
9096
9197def _map_relationship (rel : neo4j .graph .Relationship , caption_property : Optional [str ]) -> Optional [Relationship ]:
9298 if rel .start_node is None or rel .end_node is None :
9399 return None
94100
101+ top_level_fields = {"id" : rel .element_id , "source" : rel .start_node .element_id , "target" : rel .end_node .element_id }
102+
95103 if caption_property :
96104 if caption_property == "type" :
97- caption = rel .type
105+ top_level_fields [ " caption" ] = rel .type
98106 else :
99- caption = str (rel .get (caption_property ))
100- else :
101- caption = None
102-
103- base_rel_props = dict (
104- id = rel .element_id ,
105- source = rel .start_node .element_id ,
106- target = rel .end_node .element_id ,
107- _type = rel .type ,
108- caption = caption ,
109- )
110-
111- protected_props = base_rel_props .keys ()
112- additional_rel_props = {k : v for k , v in rel .items ()}
113- additional_rel_props = _rename_protected_props (additional_rel_props , protected_props )
114-
115- return Relationship (
116- ** base_rel_props ,
117- ** additional_rel_props ,
118- )
119-
120-
121- def _rename_protected_props (
122- additional_props : dict [str , Any ],
123- protected_props : Iterable [str ],
124- ) -> dict [str , Union [str , int , float ]]:
125- for prop in protected_props :
126- if prop not in additional_props :
107+ top_level_fields ["caption" ] = str (rel .get (caption_property ))
108+
109+ properties = {}
110+ for prop , value in rel .items ():
111+ if prop not in Relationship .model_fields .keys ():
112+ properties [prop ] = value
127113 continue
128114
129- additional_props [f"__{ prop } " ] = additional_props .pop (prop )
115+ if prop in top_level_fields :
116+ properties [prop ] = value
117+ continue
118+
119+ top_level_fields [prop ] = value
120+
121+ if "type" in properties :
122+ properties ["__type" ] = properties ["type" ]
123+ properties ["type" ] = rel .type
130124
131- return additional_props
125+ return Relationship ( ** top_level_fields , properties = properties )
0 commit comments