2828 node_attr_dict_factory ,
2929 node_dict_factory ,
3030)
31- from .function import get_node_id
31+ from .function import cast_to_string , get_node_id
3232from .reportviews import ArangoEdgeView , ArangoNodeView
3333
3434networkx_api = nxadb .utils .decorators .networkx_class (nx .Graph ) # type: ignore
@@ -247,6 +247,7 @@ def __init__(
247247 self .clear = self .clear_override
248248 self .clear_edges = self .clear_edges_override
249249 self .add_node = self .add_node_override
250+ # self.add_nodes_from = self.add_nodes_from_override
250251 self .number_of_edges = self .number_of_edges_override
251252 self .nbunch_iter = self .nbunch_iter_override
252253
@@ -599,6 +600,24 @@ def chat(
599600
600601 return str (response ["result" ])
601602
603+ def _get_smart_id (self , node_for_adding : str , attr : dict [Any , Any ]) -> str :
604+ raise NotImplementedError (
605+ "This is broken if node_for_adding is structured like an ArangoDB ID"
606+ ) # noqa: E501
607+ # Should we really be doing this? Database would catch this error anyways...
608+
609+ if self .smart_field not in attr :
610+ m = f"Node { node_for_adding } missing smart field '{ self .smart_field } '" # noqa: E501
611+ raise KeyError (m )
612+
613+ # TODO: Revisit this behaviour.
614+ # Too magical? Raise error instead? Let ArangoDB handle it?
615+ node_for_adding = cast_to_string (node_for_adding )
616+ if ":" not in node_for_adding :
617+ node_for_adding = f"{ attr [self .smart_field ]} :{ node_for_adding } "
618+
619+ return node_for_adding
620+
602621 #####################
603622 # nx.Graph Overides #
604623 #####################
@@ -663,10 +682,19 @@ def clear_edges_override(self):
663682 nx ._clear_cache (self )
664683
665684 def add_node_override (self , node_for_adding , ** attr ):
666- if node_for_adding not in self ._node :
667- if node_for_adding is None :
668- raise ValueError ("None cannot be a node" )
685+ if node_for_adding is None :
686+ raise ValueError ("None cannot be a node" )
687+
688+ # New:
689+ # if self.is_smart:
690+ # node_for_adding = self._get_smart_id(node_for_adding, attr)
669691
692+ # Reason:
693+ # Support for ArangoDB Smart Graphs requires the smart field
694+ # to be set before adding the node to the graph. This is because
695+ # the smart field is used to generate the node's key.
696+
697+ if node_for_adding not in self ._node :
670698 self ._adj [node_for_adding ] = self .adjlist_inner_dict_factory ()
671699
672700 ######################
@@ -679,23 +707,14 @@ def add_node_override(self, node_for_adding, **attr):
679707
680708 # New:
681709 node_attr_dict = self .node_attr_dict_factory ()
682-
683- if self .is_smart :
684- if self .smart_field not in attr :
685- m = f"Node { node_for_adding } missing smart field '{ self .smart_field } '" # noqa: E501
686- raise KeyError (m )
687-
688- node_attr_dict .data [self .smart_field ] = attr [self .smart_field ]
689-
710+ node_attr_dict .data = attr
690711 self ._node [node_for_adding ] = node_attr_dict
691- self ._node [node_for_adding ].update (attr )
692712
693713 # Reason:
694- # Invoking `update` on the `attr_dict` without `attr_dict.node_id` being set
695- # i.e trying to update a node's attributes before we know _which_ node it is
696- # Furthermore, support for ArangoDB Smart Graphs requires the smart field
697- # to be set before adding the node to the graph. This is because the smart
698- # field is used to generate the node's key.
714+ # We can optimize the process of adding a node by creating avoiding
715+ # the creation of a new dictionary and updating it with the attributes.
716+ # Instead, we can create a new node_attr_dict object and set the attributes
717+ # directly. This only makes 1 network call to the database instead of 2.
699718
700719 ###########################
701720
@@ -704,6 +723,10 @@ def add_node_override(self, node_for_adding, **attr):
704723
705724 nx ._clear_cache (self )
706725
726+ # TODO: Address in separate PR
727+ # def add_nodes_from_override(self, nodes_for_adding, **attr):
728+ # raise NotImplementedError("Not yet implemented")
729+
707730 def number_of_edges_override (self , u = None , v = None ):
708731 if u is not None :
709732 return super ().number_of_edges (u , v )
0 commit comments