neomodel
neomodel copied to clipboard
Unexpected behaviour with `get_or_create`
Hey there! This isssue seems very similar to this issue: https://github.com/neo4j-contrib/neomodel/issues/462
However I decided to create a new one - let me know if you like me to merge this with above.
This issue illustrates some strange behaviour when using get_or_create
in this code:
from neomodel import StructuredNode
from neomodel import StringProperty, IntegerProperty
from neomodel import RelationshipFrom, RelationshipTo
class Movie(StructuredNode):
oid = StringProperty(unique_index=True)
title = StringProperty()
genres = RelationshipTo("Genre", "IS_KIND")
class Genre(StructuredNode):
name = StringProperty()
genre_id = IntegerProperty(unique_index=True)
movies = RelationshipFrom('Movie', "IS_KIND")
movies_data = [{'oid': '8844', 'title': 'Jumanji'},{'oid': '862','title': 'Toy Story'}]
genre_data =[
[{'genre_id': 16, 'name': 'Animation'}, {'genre_id': 35, 'name': 'Comedy'}, {'genre_id': 10751, 'name': 'Family'}],
[{'genre_id': 12, 'name': 'Adventure'}, {'genre_id': 14, 'name': 'Fantasy'},{'genre_id': 10751, 'name': 'Family'}]
]
movie_objects = Movie.get_or_create(*movies_data)
for n, genre in enumerate(genre_data):
Genre.get_or_create(*genre, relationship=movie_objects[n].genres)
When I run the above I get this error:
Traceback (most recent call last):
File "/Users/rafmello/GitHub/oscar-worthy/python/lib/python3.7/site-packages/neomodel/util.py", line 212, in cypher_query
response = session.run(query, params)
File "/Users/rafmello/GitHub/oscar-worthy/python/lib/python3.7/site-packages/neo4j/__init__.py", line 492, in run
self._connection.fetch()
File "/Users/rafmello/GitHub/oscar-worthy/python/lib/python3.7/site-packages/neobolt/direct.py", line 422, in fetch
return self._fetch()
File "/Users/rafmello/GitHub/oscar-worthy/python/lib/python3.7/site-packages/neobolt/direct.py", line 464, in _fetch
response.on_failure(summary_metadata or {})
File "/Users/rafmello/GitHub/oscar-worthy/python/lib/python3.7/site-packages/neobolt/direct.py", line 759, in on_failure
raise CypherError.hydrate(**metadata)
neobolt.exceptions.ConstraintError: Node(53687) already exists with label `Genre` and property `genre_id` = 16
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "help.py", line 30, in <module>
Genre.get_or_create(*genre, relationship=movie_objects[n].genres)
File "/Users/rafmello/GitHub/oscar-worthy/python/lib/python3.7/site-packages/neomodel/core.py", line 433, in get_or_create
results = db.cypher_query(query, params)
File "/Users/rafmello/GitHub/oscar-worthy/python/lib/python3.7/site-packages/neomodel/util.py", line 33, in wrapper
return func(self, *args, **kwargs)
File "/Users/rafmello/GitHub/oscar-worthy/python/lib/python3.7/site-packages/neomodel/util.py", line 223, in cypher_query
raise UniqueProperty(ce.message)
neomodel.exceptions.UniqueProperty: Node(53687) already exists with label `Genre` and property `genre_id` = 16
Failed to write data to connection Address(host='localhost', port=7687) (Address(host='::1', port=7687, flow_info=0, scope_id=0)); ("0; 'Underlying socket connection gone (_ssl.c:2263)'")
Failed to write data to connection Address(host='localhost', port=7687) (Address(host='::1', port=7687, flow_info=0, scope_id=0)); ("0; 'Underlying socket connection gone (_ssl.c:2263)'")
This behaviour is unexpected because I am looking to utilize the unique_index
on the Genre model to get genre's that already exist.
Running: neomodel==3.3.2
Any updates on this? I am experiencing the same issue.
Update from my side: It does work when you use a UniqueIdProperty
, even when you supply a value that is other than the default value.
There are two differences when you use the UniqueIdProperty
compared to the string property: 1) It inherits from Property instead of NormalizedProperty 2) It ignores the kwargs and it sets a default value as well as unique_index=True (https://github.com/neo4j-contrib/neomodel/blob/da8b1e4322c64490dd83a0b62eacf77fe2f85b3e/neomodel/properties.py).
As the NormalizedProperty does not define a construct itself, it seems unlikely to me that the problem arises there. So this leaves me with option 2 - maybe it is required to set a default value (or as it is mutually exclusive) the required kwarg.
I tested that now and setting required = True seems to do the job.
Seems fixed based on comment, so closing for cleaning up the Issues log. Feel free to re-open