-
Notifications
You must be signed in to change notification settings - Fork 243
Open
Labels
Milestone
Description
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