Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArrayProperty includes filters operator #820

Open
wbenbihi opened this issue Jul 23, 2024 · 0 comments · May be fixed by #821
Open

ArrayProperty includes filters operator #820

wbenbihi opened this issue Jul 23, 2024 · 0 comments · May be fixed by #821
Milestone

Comments

@wbenbihi
Copy link

Feature description

I am currently reaching a limitation in neomodel properties/relationship filtering regarding ArrayProperty.
While #379 and #784 seem to be related, to my understanding it does not filter the NodeSet based on inclusion.

To illustrate this with an example, we define a relationship containing an ArrayProperty, I thought of __includes / __includes_all / __includes_any operators to filter the NodeSet.

from neomodel import StructuredNode
from neomodel import StructuredRel
from neomodel import StringProperty
from neomodel import ArrayProperty
from neomodel import ZeroOrMore
from neomodel import RelationshipTo
from neomodel import RelationshipFrom

class MemberOfRelationship(StructuredRel):
    permissions = ArrayProperty(StringProperty(), required=True)

class User(StructuredNode):
    name = StringProperty(required=True)
    tags = ArrayProperty(StringProperty(), required=True)
    organizations =  RelationshipTo('Organization', "MEMBER_OF", model=MemberOfRelationship, cardinality=ZeroOrMore)

class Organization(StructuredNode):
    name = StringProperty(required=True)
    members =  RelationshipFrom('User', "MEMBER_OF", model=MemberOfRelationship, cardinality=ZeroOrMore)

u = User(name="john", tags=["user", "member", "dummytag"])
o1 = Organization(name="org1")
o2 = Organization(name="org2")

o1.members.connect(u, properties={"permissions": ["read",  "write", "delete"]})
o2.members.connect(u, properties={"permissions": ["read"]})

# How it should behave

User.nodes.filter(tags__includes = "dummytag")
# MATCH (u:User) WHERE "dummytag" IN u.tags RETURN u
> User(name="john", tags=["user", "member", "dummytag"])

User.nodes.filter(tags__includes_any = ["dummytag"])
# MATCH (u:User) WHERE any(x IN ["dummytag"] WHERE x IN u.tags) RETURN u
> User(name="john", tags=["user", "member", "dummytag"])

User.nodes.filter(tags__includes_all = ["dummytag"])
# MATCH (u:User) WHERE all(x IN ["dummytag"] WHERE x IN u.tags) RETURN u
> User(name="john", tags=["user", "member", "dummytag"])

u.organizations.match(permissions__includes = "read")
# MATCH (u:User) WITH u MATCH (u)-[r:MEMBER_OF]->(o:Organization) WHERE "read" IN r.permissions RETURN o
> [Organization(name="org1"), Organization(name="org2")]

u.organizations.match(permissions__includes_all = ["write", "read"])
# MATCH (u:User) WITH u MATCH (u)-[r:MEMBER_OF]->(o:Organization) WHERE all(x IN ["write", "read"] WHERE x IN r.permissions) RETURN o
> [Organization(name="org2")]

u.organizations.match(permissions__includes_any = ["write", "read"])
# MATCH (u:User) WITH u MATCH (u)-[r:MEMBER_OF]->(o:Organization) WHERE any(x IN ["write", "read"] WHERE x IN r.permissions) RETURN o
> [Organization(name="org1"), Organization(name="org2")]

How this feature can improve the project?

While this behavior is achievable with Cypher Queries + Neomodel's class resolution. I think neomodel can benefit from this additional operation to stay consistent with already existing operators.

I can try to open a PR to implement such a feature, but I'd like to know if it is really relevant for neomodel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants