在 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)

保存时,它会添加标签Label1Label2Label3到创建的节点

可以用子类来完成,例如:

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 user3280193neomodel 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 正式提倡 inheritancemixins。阅读更多:

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 自己编写密码查询。