我正在使用带有 Neo4j 数据库的 Neomodel Python 包,并且很喜欢它。 我当前正在使用 filter() 方法,但每次我对 SemiStructuredNode 中未定义的属性使用 filter() 方法时,都会收到错误。
在下面的示例中,我的 Person SemiStructuredNode 仅以姓氏作为属性,但数据库中的某些节点可能也有 eye_colour,我想通过它进行过滤。 请注意,并非所有节点都有眼睛颜色。
class Person(SemiStructuredNode):
surname = StringProperty()
Person.nodes.filter(surname__contains='atts',eye_colour='BLUE')
对我来说,上面的代码应该可以工作,但我收到了
ValueError: No such property eye_colour on Person
错误。 但是,如果我更改类定义以将 eye_colour 作为 StringProperty 包含在内,则一切都很好。 但是,我不想这样做,因为我想使用各种其他动态过滤器,因为不同的数据被导入到系统中。
Neomodel 是否支持我正在尝试做的事情,或者我必须构建一个密码查询或者有人可以看到我做错了什么吗?
你确实发现了 Neomodel 中的一个限制。虽然
SemiStructuredNode
非常适合处理灵活的架构,但 Neomodel 的
filter()
方法目前无法处理没有为类定义为属性的动态属性。
可选解决方法
1. 原始密码查询
为了获得最大的灵活性,你可以使用原始密码查询。这使你可以完全控制过滤逻辑。
from neomodel import db
results, meta = db.cypher_query(
"MATCH (p:Person) WHERE p.surname CONTAINS 'atts' AND p.eye_colour = 'BLUE' RETURN p"
)
# 将结果映射回 Person 实例(如果需要)
people = [Person.inflate(row[0]) for row in results]
2. 动态属性访问
你可以使用
__getattr__
和
__contains__
在
SemiStructuredNode
类中添加一个自定义方法,以直接在节点数据上运行检查:
class SemiStructuredNode(StructuredNode):
def has_property_value(self, prop, value):
return prop in self and self[prop] == value
class Person(SemiStructuredNode):
surname = StringProperty()
filtered_people = [p for p in Person.nodes.filter(surname__contains='atts')
if p.has_property_value('eye_colour', 'BLUE')]
限制
请记住,这些解决方法有一些权衡:
- 密码查询: 虽然提供了灵活性,但需要你手动将结果映射回 Neomodel 对象。
-
动态属性访问:
在
filter()
之后需要一个额外的循环来进行过滤,这对于大型数据集来说效率可能较低。
结论
目前,你必须使用变通方法来使用 Neomodel 过滤
SemiStructuredNode
中的未定义属性。选择最适合你需求的方法,同时牢记每个选项的优缺点。