Giter Site home page Giter Site logo

neo4j-contrib / neomodel Goto Github PK

View Code? Open in Web Editor NEW
906.0 49.0 228.0 1.99 MB

An Object Graph Mapper (OGM) for the Neo4j graph database.

Home Page: https://neomodel.readthedocs.io

License: MIT License

Python 99.82% Shell 0.18%
neo4j python ogm

neomodel's People

Contributors

a-takahashi223 avatar aanastasiou avatar bleib1dj avatar curious-broccoli avatar fpieper avatar funkyfuture avatar j-krose avatar jvalhondo avatar kupuguy avatar leonaidus avatar mar-chi-pan avatar mardanovtimur avatar mariusconjeaud avatar mattgalvis avatar maximbr avatar mprahl avatar neoecos avatar nossila avatar olehchyhyryn avatar pkatseas avatar rafaelpivato avatar robertlagrant avatar robinedwards avatar siddharthm avatar technige avatar they4kman avatar tjakobsen avatar tonioo avatar whatsocks avatar ysn2233 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

neomodel's Issues

Stand alone indexed properties

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

[QUESTION] unique values

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?

index.get/search fails with string properties with embedded spaces.

>>> 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.

Error when call the method save()

Hi..

I'm new at Neo4j. I have error with call the method save() from my file models.py. I install neomodel with pip install neomodel but I don't know this error.
Anyone have an idea?.

Features installed:

  • Django 1.4
  • Python 2.7
  • Neo4j 1.8 community
  • Neomodel
  • py2neo

Thanks.

image

StructuredNode inheritance

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),

  • in a Relationship definition, the end node can't be 'A' but needs to be ['B', 'C']
  • an index defined in A will lead to indices in subclasses, but not a shared index. (is it possible to share an index between subclasses?)
  • anything else to consider?

Provide key name on type validation error

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

Relationship weight - pure performance with relationship insert

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.

Using __init__(self, ...) in models

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__?

Tidy up inheritance

  • remove support for connecting to sub classes
  • remove _index_name class attribute

problematic 'default=function' functionality

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

Feature request: traverse extra functionality

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)

REST interface performance

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,

version naming

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 ?

neomodel and thread safe variables

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?

Property instances of unsaved node objects behave unexpectedly

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.

deprectation warning

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?

Search fails in a nasty way without any arguments

>>> 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?

[Feature Request] Smart Creation

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 !!

[Feature Request] Expose all Nodes/Rel Functionnality

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 !!

[Feature Request] Defining & Accessing Relationship Attribute

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

DoesNotExist class creation explanation

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.