neo4j-contrib / neomodel Goto Github PK
View Code? Open in Web Editor NEWAn Object Graph Mapper (OGM) for the Neo4j graph database.
Home Page: https://neomodel.readthedocs.io
License: MIT License
An Object Graph Mapper (OGM) for the Neo4j graph database.
Home Page: https://neomodel.readthedocs.io
License: MIT License
Hi,
With a recent update, i was able to share index on subclasses, and it helped in order to find any node type using just one index and just one property (uuid).
Today, i noticed this approach outcome with some ussues, like having indexed a property with the same name on different classes, and worst if is a unique_index.
Also I'll should be to be able to do a text search on other properties of some classes, looking for indexing information, i found there are other types of index on lucene, specific there is a fulltext type of index for search for text within fields of the node.
Now, i think a possible solution for this could be standalone indexes for properties, so is possible to share and index for a common property, and use specific type of index for same kind of properties.
Probably i will be able to work on this feature within the end of this month, and would be useful your comments and ideas.
So, now i'm thin
I would like to ask if there exists or if it could be possible to exist the unique entry of an entity in my database.
How could i avoid duplicates?
In django there exists :
class Meta:
unique_together = (('attribute1', 'attribute2'), )
Is there anything similar in neomodel or could i just use that it should work?
bind(Person, "country", "is_from", OUTGOING, Country)
>>> import neomodel
>>> class Foo(neomodel.StructuredNode):
... prop = neomodel.StringProperty(unique_index=True)
...
>>> f1 = Foo(prop="Test")
>>> f1.save()
<__main__.Foo object at 0x7fe1e4508b90
>>>> Foo.index.get(prop="Test")
<__main__.Foo object at 0x7fe1e211ffd0>
>>> f2 = Foo(prop="Te st")
>>> f2.save()
<__main__.Foo object at 0x7fe1e211ffd0>
>>> Foo.index.get(prop="Te st")
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/src/neomodel/neomodel/index.py", line 36, in _execute
return self.__index__.query(query)
File "/lib/python3.3/site-packages/py2neo/neo4j.py", line 2044
, in query
self.__uri__, quote(query, "")
File "/lib/python3.3/site-packages/py2neo/rest.py", line 428,
in _send
return self._client().send(request)
File "/lib/python3.3/site-packages/py2neo/rest.py", line 365,
in send
return Response(request.graph_db, rs.status, request.uri, rs.getheader("Location", None), rs_body)
File "/lib/python3.3/site-packages/py2neo/rest.py", line 279,
in __init__
raise SystemError(body)
SystemError: {'exception': 'NullPointerException', 'stacktrace': [...]}
The error seems to be something to do with Foo.index._execute
. Running Foo.index._execute("prop:Te st")
causes the Null Pointer exception, but doing Foo.index._execute("prop:\"Te st\"")
returns the correct value. I notice that the search
and get
methods do seem to do some escaping, but that seems to be tied up with a rather scary looking regex, so I didn't dig much further.
I don't know if it's worth reporting a bug with neo4j proper (or whoever is responsible for this); a null pointer exception shouldn't really be happening for something as simple as an invalid query.
This is all on Python 3.3.2, though I don't think it should make too much of a difference for this particular issue.
.
Hi,
I've tried to get class inheritance and StructuredNodes work together. I've noted that it generally works but with a few caveats:
Lets say given A(StructuredNode)
which is never instantiated, and B(A)
, C(A)
,
'A'
but needs to be ['B', 'C']
A
will lead to indices in subclasses, but not a shared index. (is it possible to share an index between subclasses?)Traceback (most recent call last):
File "", line 1, in
File "/Users/rob/dev/sharehood/venv/src/neomodel/neomodel/core.py", line 136, in init
self._validate_args(kwargs)
File "/Users/rob/dev/sharehood/venv/src/neomodel/neomodel/core.py", line 183, in _validate_args
node_property.validate(value)
File "/Users/rob/dev/sharehood/venv/src/neomodel/neomodel/properties.py", line 21, in validate
raise TypeError("Object of type str expected got " + str(value))
TypeError: Object of type str expected got None
Hey, I tried to create weighted edges (relationships) between nodes. Resulting in this Code:
class TokenRel(StructuredRel):
weight = IntegerProperty(default = 1)
class TokenNode(StructuredNode):
identifier = StringProperty(unique_index = True, required = True)
occurence = Relationship('TokenNode', 'OCCURENCE', model = TokenRel)
But when I create two Nodes and try to double connect them with these two statements:
token1.occurence.connect(token2)
token1.occurence.connect(token2)
I only retrieve from print(token1.occurence.count()) one edge. Assuming it should be two.
So I tried something like this (Asume all nodes are inserted):
def _createRelationship(self, node, tokenAsNodes):
for to in tokenAsNodes:
if node.occurence.is_connected(to):
self._increaseEdgeWeight(node, to)
else:
node.occurence.connect(to)
def _increaseEdgeWeight(self, firstNode, secondNode):
rel = firstNode.occurence.relationship(secondNode)
rel.weight += 1
rel.save()
with createRelationship(TokenNode.index.get(identifier = 'someNode), TokenNode.index.get(identifier = 'SomeOtherNode)).
Unfortunately I have to create a big amount of relationships. So my solution offers pure performance, because of the single transactions to the database. What is the best practice to model edge weight and insert a large amount of relationships. Only found batch insert for nodes.
Regards.
denmark.people.search(age=3)
I'm used to having my own init() function in models which basically do following:
class Foo(StructuredNode):
prop = StringProperty()
def __init__(self, prop):
self.prop = prop
Now currently when saving that node, the save()
function(in core.py
) checks whether object's __node__
property is false which fails because the __node__
property does not yet exist.
Is there a rationale for that or could the if self.__node__
check be changed into if hasattr(self, __node__) and self.__node__
?
ONE, ZERO_OR_ONE, ZERO_OR_MORE...
.
.
The properties default=<function body>
functionality is a bit problematic as it doesn't enforce unicode return values.
E.g. given a class:
class ExampleNode(StructuredNode):
...
uuid = StringProperty(unique_index=True, default=uuid4)
...
we'll find this behaviour in a python shell:
>>> e = Example()
>>> type(e.uuid)
<class 'uuid.UUID'>
>>> e.save()
>>> type(e.uuid)
<class 'uuid.UUID'>
>>> e.refresh()
>>> type(e.uuid)
<type 'unicode'>
so depending on when you call the attribute, it will behave quite differently.
Another issue is that some defaults need functions with arguments. At least, I believe this is the only way to handle e.g. a "current timestamp" default to a DateTimeProperty():
datetime.now(pytz.utc)
For both cases I can write custom wrappers but if that's the solution it may be worth mentioning as a best practice in the docs
pip install six
Hello,
I was wondering if there could be a way to filter by relations. For example if we want to get the results of
start_node.traverse('property')
where the resulting nodes are localised and we only want the ones connected to 'en'.
So something like:
start_node.traverse('property').is_connected(english_node)
Also, we could have something similar when we don't want it to be connected, like:
start_node.traverse('property').is_connected(english_node, False)
or
start_node.traverse('property').is_not_connected(english_node)
Hi everybody, anyone have done any benchmark on the REST interface of neo4j using neomodel and /or py2neo
I was trying to import some nodes (1.8M) with 26 properties from a CSV file and is frustrating, i tunned the neo4j and still is un usable.
No relationships.
I am aware of https://github.com/jexp/batch-import but just i can imagine a production enviroment with this configuration using neomodel.
Thank you,
Hi Robin,
I guess if your following some standart notation?
What happend is that in the last version 0.3.6 you made some changes that are not backward compatibles like moving the RelationshipManager and RelationshipDefinition class to another module.
Maybe it's time for 0.4.0 ?
I have an issue with relationship validation in flask. (I believe this could be re-created in other frameworks as well as they might employ similar techniques.)
I'm using the (thread safe) g global to store my user class during the session.
When I make 2 parallel requests to the app, it seems that to warrant thread-safety, flask replaces the "user" class with a proxy class <class 'werkzeug.local.LocalProxy'>
(http://werkzeug.pocoo.org/docs/local/).
Which then violates neomodel constraints when I try to connect something to the user.
File "neomodel/relationship.py", line 94, in connect
+ allowed_cls + " got " + obj.__class__.__name__)
Exception: connect expected objects of class X got LocalProxy
Is there a good approach to handle this?
provide mechanism for generating uid
.
Let's assume a StructuredNode subclass Foo. When instantiating a Foo object (or in fact even through the Foo class itself), any Property instances of the object which don't have a default value specified in their definition will return something equivalent to <neomodel.properties.StringProperty at 0x2de36d0>
when referring to them.
This is not very intuitive and can actually cause problems when trying to check against such values by doing for example if myobj.name:
, as that will always be True (since there's a Property object in place). One would then have to be aware of the PropertyType and do some custom checking along the lines of if isinstance(myobj.name, basestring):
, which is not ideal.
I suppose there are a number of ways to deal with this situation. Django for example hides fields of a model instance behind a Meta class. So if you try to access a field from the model class (without an instance of the class), you get an AttributeError
. If you do instantiate and try to access the field, you get a default value for it (empty string, False, None, etc.). Hiding away the properties doesn't sound like the best way forward, but default values do. For example, if there is a default value specified for a property, use that, otherwise return None.
I hope we can start a discussion on this and figure out what works best before moving on to implementing a fix. Also, as this might break existing code, it would probably be better to include the fix in the next major version.
BadInputException: The property 'code' does not exist on Node[441]
It would be nice to have sorting and limiting for Object.category().instance
.
add pre and post save hooks
also include expected types and node ids
When saving a node, I get this:
>>> e.save()
/[...]/src/neomodel/neomodel/core.py:176: DeprecationWarning: WriteBatch.create_node is deprecated, use WriteBatch.create instead.
batch.create_node(p)
/[...]/src/neomodel/neomodel/core.py:179: DeprecationWarning: WriteBatch.create_relationship is deprecated, use WriteBatch.create instead.
cls.relationship_type(), i, {"__instance__": True})
<evidences.models.Evidence object at 0x1023f4710>
I did not call WriteBatch.create_node
myself. It seems one of the internal function of neomodel still uses this old function instead of .create
?
node.delete()
node.foo.connect(new) # "Node has not been saved cannot connect
>>> class Foo(StructuredNode):
... prop = StringProperty(index=True)
...
>>> Foo.index.search()
<Horrible ugly traceback that doesn't really explain the problem to user>
It seems that search
method doesn't handle a completely empty argument list (though all arguments are optional), so the query
variable ends up being an empty string, which means we then get a parse error from neo4j about EOF in line 1, column 0.
I'm not sure what the expected behaviour is; intuitively, calling search with no paramaters makes me think it will return all objects, but given the existance of other methods to do that, maybe a simple (more explanitory) exception will suffice?
Hi Team,
Again, Feature Request posted in an issue.
Looking for a way to do some smart_creation.
Something like
class MyNode(StructuredNode):
....name=StringProperty(primaryKey=True)
first=MyNode(name="One").save() #Node creation take place
second=MyNode(name="One").save() # No new node created=> the indexed one is used
second == first #-> True.
The point would, in this case, to use the GDB.get_or_create_indexed_node from Py2Neo.
Sorry if it already exists.
Thanks !!
Makes numerous REST requests could be achieved in a single cypher
A new feature request.
As a side, I did try to create my own ORM for Neo4j. That's why I come up with so many feature's requests ! Sorry
Now, for the request: it would be nice to expose some node's & rel's features to the StructuredNode Class (resp. to the future RelationshipClass asked in another feature request :))
As an example, I'm not able, from a given node, to ask for all related nodes, or to ask for all incoming relationships.
Thanks !!
.
Hi All,
Great works. I do not know where to post my feature request, so it's gonna be an incident.
While checking the API, I was not able to find a way to both define & query the Property of a relationship.
Nevertheless, this is permitted on a Neo4J Level.
Any way one could implement it ?
Or maybe subclassing RelationShipTo & From would suffice ?
Thanks & congrats for this excellent work
Hello, I was having a problem with the DoesNotExist instantition on neomodel/index.py
Context, just looking for node using de IndexManager of the object.
if 'uuid' in kwargs:
try:
node = CaliopeNode.index.get(uuid=kwargs['uuid'])
self.task = Task().__class__.inflate(node.__node__)
except DoesNotExist:
if kwargs['uuid'] in TaskServices.task_requested_uuid:
TaskServices.task_requested_uuid.remove(kwargs['uuid'])
self.task = Task()
else:
raise DoesNotExist("Invalid UUID")
In the core.py:
class StructuredNodeMeta(type):
def __new__(mcs, name, bases, dct):
dct.update({'DoesNotExist': type('DoesNotExist', (DoesNotExist,), dct)})
inst = super(StructuredNodeMeta, mcs).__new__(mcs, name, bases, dct)
...
So all the DoesNotExist attribute in every extended class of StructuredNodeBase, the type of DoesNotExists, became a new type within the same namespace, so the type(CaliopeNode.DoesNotExists)
is CaliopeNode.module.DoesNotExists, because i did from neomodel.exceptios import DoesNotExists
and with the same class dictionary additional to exception dictionary.
This approach let us catch the DoesNotExists exception like a default object of the same node class, and work with it.
The bug, or at least what i think it can be, is on index.py, when it can not find any suitable nodes to the get/search
elif len(nodes) > 1:
raise Exception("Multiple nodes returned from query, expected one")
else:
raise self.node_class.DoesNotExist("Can't find node in index matching query")
In the first snippet, the raise in index.py return an exception super(type, obj): obj must be an instance or subtype of type
I haven't think about, but maybe is because the raise is waiting for a subclass(obj, Exception), and because of the new type of DoesNotExists it fails.
Just like a workarround i writed a small patch and commited to my repo, and for me its working without the behaviour of default node on the DoesNotExists exception.
neoecos@59f1ede#diff-0
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.