在 Neomodel 中使用多个标签
Using multiple labels with Neomodel
我想知道是否可以通过 NeoModel 将不同的标签关联到 class。如果没有,哪个模块可以让我这样做?
我的理解是,当使用下面的class声明时,"Person"是一个标签。
class Person(StructuredNode):
name = StringProperty(unique_index=True)
age = IntegerProperty(index=True, default=0)
假设我想添加第二个标签,"Employed"、"Unemployed"、"Student"。
有了 Cypher,我可以使用:
CREATE(p:Person:Student)
我能用 NeoModel 实现同样的效果吗?
备注:
根据我的研究,使用标签比使用属性 (neo4j/cypher) 产生更快的查询,这就是为什么我希望 employed/unemployed/student 成为标签。否则我可以添加 "occupation" 作为节点 属性.
目前没有向新模型结构化节点添加标签的方法,但这可以通过密码来完成。我也很乐意添加一种方法来执行此操作。您必须注意标签不要与 class 名称冲突。您可以通过其 labels() 方法 return 节点的标签
您可以简单地破解 __label__
属性、
class Person(StructuredNode):
__label__ = 'Label1:Label2:Label3'
name = StringProperty(unique_index=True)
age = IntegerProperty(index=True, default=0)
保存时,它会添加标签Label1
、Label2
和Label3
到创建的节点
可以用子类来完成,例如:
class Person(StructuredNode):
name = StringProperty(unique_index=True)
age = IntegerProperty(index=True, default=0)
class PersonSub(Person):
pass
然后,实例化子类并调用labels()方法:
psub = PersonSub(name = 'Person Sub', age=30).save()
psub.labels() #['Person', 'PersonSub']
您也可以使用密码查询来验证:
psub.cypher("MATCH (a:PersonSub) RETURN a")
截至 2020 年,虽然使用 All Іѕ Vаиітy doesn't produce the desired outcome. Therefore the answer from user3280193 的 neomodel 4.0.1
答案是最正确的,但并非没有小警告,所以让我详细说明一下。
标签黑客攻击(不推荐!)
首先让我们看看为什么标签黑客攻击是有缺陷的:
class Unemployed(StructuredNode):
__label__ = 'Person:Unemployed'
name = StringProperty(unique_index=True)
Unemployed(name='Carol').save()
如果您检查,即使节点已正确保存在数据库中,它也无法在以后正确检测到节点:
print(len(Unemployed.nodes)) # prints 0
人们可能会认为,如果我们有另一个 class Person
,那么我们就可以那样检索它 - 不幸的是没有。自己看看:
class Unemployed(StructuredNode):
__label__ = 'Person:Unemployed'
name = StringProperty(unique_index=True)
class Person(StructuredNode):
name = StringProperty(unique_index=True)
Unemployed(name='Carol').save()
到目前为止一切顺利,让我们尝试获取一些节点。下面的结果看起来不错。
print(len(Person.nodes)) # prints 1
但是,当我们试图访问那个节点时,问题就会出现:
print(Person.nodes[0])
# Results in two exceptions
#
# Traceback (most recent call last):
# ...
# KeyError: frozenset({'Person', 'Unemployed'})
#
# During handling of the above exception, another exception occurred:
# ...
# neomodel.exceptions.ModelDefinitionMismatch: <exception str() failed>
我不会详细说明为什么会发生这种情况,只是说 neomodel 无法应对标签黑客攻击,因为它不是为此设计的。如果有人想了解这种行为,我建议查看库的 neomodel.core
部分。
继承
neomodel 正式提倡 inheritance 和 mixins。阅读更多:
https://neomodel.readthedocs.io/en/latest/extending.html#inheritance
https://neomodel.readthedocs.io/en/latest/extending.html#mixins
由于mixins 不提供额外的标签,我将重点介绍继承。让我们假设下面的例子,我们深入 2 层继承。
class Person(StructuredNode):
name = StringProperty(unique_index=True)
class Student(Person):
pass
class Employed(Person):
pass
class EmployedStudent(Student, Employed):
pass
Person(name='Bob').save()
Student(name='Will').save()
Employed(name='John').save()
EmployedStudent(name='Kim').save()
结果:
print(len(Person.nodes)) # 4
print(len(Student.nodes)) # 2
print(len(Employed.nodes)) # 2
print(len(EmployedStudent.nodes)) # 1
这具有正确的行为,但似乎产生了一个人工制品 - 标签 EmployedStudent
。没有简单的技巧可以摆脱这个额外的标签,因为它对 automatic class resolution.
至关重要
结论:OGM 有其缺点,但我会随时选择额外的冗余标签,而不是为我构造的每个 class 自己编写密码查询。
我想知道是否可以通过 NeoModel 将不同的标签关联到 class。如果没有,哪个模块可以让我这样做?
我的理解是,当使用下面的class声明时,"Person"是一个标签。
class Person(StructuredNode):
name = StringProperty(unique_index=True)
age = IntegerProperty(index=True, default=0)
假设我想添加第二个标签,"Employed"、"Unemployed"、"Student"。
有了 Cypher,我可以使用:
CREATE(p:Person:Student)
我能用 NeoModel 实现同样的效果吗?
备注: 根据我的研究,使用标签比使用属性 (neo4j/cypher) 产生更快的查询,这就是为什么我希望 employed/unemployed/student 成为标签。否则我可以添加 "occupation" 作为节点 属性.
目前没有向新模型结构化节点添加标签的方法,但这可以通过密码来完成。我也很乐意添加一种方法来执行此操作。您必须注意标签不要与 class 名称冲突。您可以通过其 labels() 方法 return 节点的标签
您可以简单地破解 __label__
属性、
class Person(StructuredNode):
__label__ = 'Label1:Label2:Label3'
name = StringProperty(unique_index=True)
age = IntegerProperty(index=True, default=0)
保存时,它会添加标签Label1
、Label2
和Label3
到创建的节点
可以用子类来完成,例如:
class Person(StructuredNode):
name = StringProperty(unique_index=True)
age = IntegerProperty(index=True, default=0)
class PersonSub(Person):
pass
然后,实例化子类并调用labels()方法:
psub = PersonSub(name = 'Person Sub', age=30).save()
psub.labels() #['Person', 'PersonSub']
您也可以使用密码查询来验证:
psub.cypher("MATCH (a:PersonSub) RETURN a")
截至 2020 年,虽然使用 All Іѕ Vаиітy doesn't produce the desired outcome. Therefore the answer from user3280193 的 neomodel 4.0.1
答案是最正确的,但并非没有小警告,所以让我详细说明一下。
标签黑客攻击(不推荐!)
首先让我们看看为什么标签黑客攻击是有缺陷的:
class Unemployed(StructuredNode):
__label__ = 'Person:Unemployed'
name = StringProperty(unique_index=True)
Unemployed(name='Carol').save()
如果您检查,即使节点已正确保存在数据库中,它也无法在以后正确检测到节点:
print(len(Unemployed.nodes)) # prints 0
人们可能会认为,如果我们有另一个 class Person
,那么我们就可以那样检索它 - 不幸的是没有。自己看看:
class Unemployed(StructuredNode):
__label__ = 'Person:Unemployed'
name = StringProperty(unique_index=True)
class Person(StructuredNode):
name = StringProperty(unique_index=True)
Unemployed(name='Carol').save()
到目前为止一切顺利,让我们尝试获取一些节点。下面的结果看起来不错。
print(len(Person.nodes)) # prints 1
但是,当我们试图访问那个节点时,问题就会出现:
print(Person.nodes[0])
# Results in two exceptions
#
# Traceback (most recent call last):
# ...
# KeyError: frozenset({'Person', 'Unemployed'})
#
# During handling of the above exception, another exception occurred:
# ...
# neomodel.exceptions.ModelDefinitionMismatch: <exception str() failed>
我不会详细说明为什么会发生这种情况,只是说 neomodel 无法应对标签黑客攻击,因为它不是为此设计的。如果有人想了解这种行为,我建议查看库的 neomodel.core
部分。
继承
neomodel 正式提倡 inheritance 和 mixins。阅读更多:
https://neomodel.readthedocs.io/en/latest/extending.html#inheritance https://neomodel.readthedocs.io/en/latest/extending.html#mixins
由于mixins 不提供额外的标签,我将重点介绍继承。让我们假设下面的例子,我们深入 2 层继承。
class Person(StructuredNode):
name = StringProperty(unique_index=True)
class Student(Person):
pass
class Employed(Person):
pass
class EmployedStudent(Student, Employed):
pass
Person(name='Bob').save()
Student(name='Will').save()
Employed(name='John').save()
EmployedStudent(name='Kim').save()
结果:
print(len(Person.nodes)) # 4
print(len(Student.nodes)) # 2
print(len(Employed.nodes)) # 2
print(len(EmployedStudent.nodes)) # 1
这具有正确的行为,但似乎产生了一个人工制品 - 标签 EmployedStudent
。没有简单的技巧可以摆脱这个额外的标签,因为它对 automatic class resolution.
结论:OGM 有其缺点,但我会随时选择额外的冗余标签,而不是为我构造的每个 class 自己编写密码查询。