scholrly / neo4django

Drop-in Neo4j/Django integration.
GNU General Public License v3.0
358 stars 83 forks source link

relationship query #134

Closed icaria closed 11 years ago

icaria commented 12 years ago

I'm sure I'm missing something obvious, but how would you go about querying relationships in the following scenario?

a Person(NodeModel) has a Group(NodeModel), each Group(NodeModel) has a GroupType(NodeModel), each Group also has a created_date (DateProperty). I want to query all the groups a person is in that are of group_type "Chess Club" that were created after January 1st, 2012.

Here's a general model declaration to clarify:

class Person(models.NodeModel):
    groups = models.Relationship('Group', related_name='groups')

class Group(models.NodeModel):
    group_type = models.Relationship('GroupType', related_name='type')
    created_date = models.DateProperty()

class GroupType(models.NodeModel):
    type = models.StringProperty()

I tried playing around but came up with nothing that was quite what I needed...

Thanks for any assistance

mhluongo commented 12 years ago

@icaria unfortunately, you aren't missing anything. Querying against related objects is another open issue (https://github.com/scholrly/neo4django/issues/20).

As a workaround, you can either do the particular filtering you're looking for in-memory (unless a person is in a ton of groups this should work fine) or use Cypher, and wrap the results in neo4django objects. I've written a gist example using the above model definition (plus some minor enhancements). Let me know if it works for you.

mhluongo commented 12 years ago

For a similar example, check out this other gist as well.

icaria commented 12 years ago

Thanks again, the in memory queries will work fine for my case. I appreciate the quick responses; as there aren't really much resources out there to help answer quick questions for this.

mhluongo commented 12 years ago

I do what I can :) I've been meaning to put together a tutorial or example project, but haven't had the time. If you ever want to share a project or write a quick blog post, let me know and I'll do whatever I can to help!

icaria commented 11 years ago

Hmm interesting, I tried the code sample you provided.

[o for o in self.groups.all() if o.type.type == "Chess Club"]

And I'm getting a 'RelationshipInstance' object has no attribute 'type' error. It doesn't like the o.type.type, but I have my model defined pretty much identical to yours.

mhluongo commented 11 years ago

Sorry about that, I was going a little too fast. I just edited what I think was the problem.

mhluongo commented 11 years ago

For future reference, a RelationshipInstance is an attribute on the one-or-mant-side of a many-to-many or many-to-one relationship. The attribute should've been group_type with single=True set for the relationship.

icaria commented 11 years ago

Thanks again. I'll pay more attention to the single property now that I know it changes the type of object returned.

I'm kind of stuck again because I have inherited objects which are causing all kinds of issues with the query. I'm wondering if you would have a solution for this.

class Person(models.NodeModel):
    groups = models.Relationship('Group', related_name='groups')

class Group(models.NodeModel):
    group_type = models.Relationship('GroupType', related_name='type', single=True)
    created_date = models.DateProperty()

class ChildrenGroup(Group):
    supervisor = models.Relationship('Person', related_name='supervisor, single=True)

class GroupType(models.NodeModel):
    type = models.StringProperty()

The supervisor is just a made up property, in my case I want to query for all the ChildrenGroups by doing the group_type check where group_type.type == "Children Group". Then I want to further limit the list of groups to for example those groups that are supervised by "John Smith". But currently because the Person.groups.all() is returning a list of Groups and not a list of ChildrenGroups, I can't access the supervisor parameter. Is there a way to cast the neo4django object?

Thanks again for your time...

mhluongo commented 11 years ago

Absolutely! We have a similar issue in our data layer @scholrly. I've tried to come up with something more elegant than casting, but it works for now.

regular_group = Group.objects.create(group_type='Chess Club', created_date=datetime.today())
childrens_group = ChildrenGroup.from_model(regular_group)

LMK if you have any other questions!

icaria commented 11 years ago

Thank you VERY much for your help! I was able to learn a lot.