neo4j-contrib / py2neo

EOL! Py2neo is a comprehensive Neo4j driver library and toolkit for Python.
https://py2neo.org
Apache License 2.0
20 stars 8 forks source link

OGM save RelatedObjects - feature flag to keep relationships not in list of nodes #896

Open process0 opened 3 years ago

process0 commented 3 years ago

The __db_push__ function in RelatedObjects class will delete any existing relationships for a node that are not represented by the current set of nodes on push. This creates orphan nodes when adding relations via merge to an existing node with existing relationships.

I've commented out line 340 / step 2a in this function and the relationships are preserved. Would it be possible to make this a feature flag? Also, are there any problems that could arise from doing this?

process0 commented 3 years ago

This is possible by adding a field to the Model class.

--- venv/lib/python3.7/site-packages/py2neo/ogm/__init__.py     2021-05-10 15:52:20.237786016 -0400
+++ other/venv/lib/python3.7/site-packages/py2neo/ogm/__init__.py      2021-05-10 15:47:16.313949017 -0400
@@ -336,8 +337,10 @@
             tx.merge(related_object)
         # 2a. remove any relationships not in list of nodes
         subject_id = self.node.identity
-        tx.run("MATCH %s WHERE id(a) = $x AND NOT id(b) IN $y DELETE _" % self.__relationship_pattern,
-               x=subject_id, y=[obj.__node__.identity for obj, _ in related_objects])
+        if not self.subject.__preserve_relationships__:
+            tx.run("MATCH %s WHERE id(a) = $x AND NOT id(b) IN $y DELETE _" % self.__relationship_pattern,
+                   x=subject_id, y=[obj.__node__.identity for obj, _ in related_objects])
+
         # 2b. merge all relationships
         for related_object, properties in related_objects:
             tx.run("MATCH (a) WHERE id(a) = $x MATCH (b) WHERE id(b) = $y "
@@ -424,6 +427,7 @@
     __primarylabel__ = None
     __primarykey__ = None

+    __preserve_relationships__ = False  # False for existing behavior
     __ogm = None

     def __eq__(self, other):
technige commented 3 years ago

This sounds like a good feature request. I'll look into it.

process0 commented 3 years ago

@technige any update?

technige commented 3 years ago

No, not had time to look into this yet.