7

我想知道是否有办法将不同的标签与 NeoModel 关联到一个类。如果没有,什么模块可以让我这样做?

我的理解是,当使用下面的类声明时,“Person”是一个标签。

class Person(StructuredNode):
    name = StringProperty(unique_index=True)
    age = IntegerProperty(index=True, default=0)

假设我想添加第二个标签,“已就业”、“失业”、“学生”。

使用 Cypher,我可以使用: CREATE(p:Person:Student)

无论如何我可以用 NeoModel 实现同样的效果吗?

注意: 根据我的研究,使用标签比使用属性(neo4j/cypher)产生更快的查询,这就是我希望就业/失业/学生成为标签的原因。否则,我可以将“职业”添加为节点属性。

4

4 回答 4

3

截至 2020 年,虽然使用All Іѕ Vаиітyneomodel 4.0.1的回答并不会产生预期的结果。因此,来自user3280193的答案是最正确的,但并非没有一点警告,所以让我详细说明一下。


标签黑客(不推荐!)

首先让我们看看为什么标签黑客有缺陷:

class Unemployed(StructuredNode):
    __label__ = 'Person:Unemployed'
    name = StringProperty(unique_index=True)


Unemployed(name='Carol').save()

如果您检查,即使它们已正确保存在数据库中,它也无法在以后正确检测节点:

print(len(Unemployed.nodes))        # prints 0

结果 1

人们可能会认为,如果我们有另一个类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 提倡继承混合。阅读更多:

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

结果 2

这具有正确的行为,但似乎产生了一种人工制品 - 标签EmployedStudent。摆脱这个额外的标签没有简单的技巧,因为它对于自动类解析至关重要。


结论:OGM 有其缺点,但我会随时选择额外的冗余标签,而不是自己为我构建的每个类编写密码查询。

于 2020-10-20T01:10:48.373 回答
2

目前还没有向新模型结构化节点添加标签的方法,但是这可以通过 cypher 来完成。我也很乐意添加一种方法来做到这一点。您必须小心标签不与类名冲突。您可以通过其标签()方法返回节点的标签

于 2015-04-14T10:47:11.620 回答
2

你可以简单地破解__label__财产,

class Person(StructuredNode):
    __label__ = 'Label1:Label2:Label3'
    name = StringProperty(unique_index=True)
    age = IntegerProperty(index=True, default=0)

保存时,它将添加标签Label1、、Label2Label3到创建的节点

于 2017-04-17T19:59:32.223 回答
2

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

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")
于 2019-06-26T17:30:56.500 回答