py2neo ogm与多节点标签的关系

问题描述 投票:1回答:2

我想使用py2neo的OGM来表示从一种节点类型到两种节点类型的关系。

我有一个解决方案(下面)只适用于存储数据库中的节点/关系,我找不到一个在检索关系时正常工作的解决方案。

这是我的榜样。考虑从人到汽车的OWNS关系:

from py2neo.ogm import GraphObject, Property, RelatedTo
from py2neo import Graph

class Person(GraphObject):
    name = Property()
    Owns = RelatedTo("Car")

class Car(GraphObject):
    model = Property()

g = Graph(host="localhost", user="neo4j", password="neo4j")

# Create Pete
p = Person()
p.name = "Pete"  

# Create Ferrari
c = Car()
c.model = "Ferrari"

# Pete OWNS Ferrari
p.Owns.add(c)

# Store
g.push(p)

这很好用。现在,让我们假设一个人也拥有一个房子(这个代码从上面的代码继续):

class House(GraphObject):
    city = Property()

# Create House
h = House()
h.city = "New York"

# Pete OWNS House in New York
p.Owns.add(h)

# Update
g.push(p)

OWNS关系的“到”结束应该指向汽车,而不是房子。但显然py2neo并不关心那么多,并按照预期将所有内容存储在数据库中:通过OWNS关系连接的人员,汽车和房屋。

现在的问题是使用上面的类来检索节点和关系。正确加载节点属性时,关系不是:

p = Person.select(g).where(name="Pete").first()
for n in list(p.Owns):
    print type(n).__name__

这导致:

Car
Car

此行为与类对象一致。

如何在py2neo.ogm中使用相同的类建模“人OWNS汽车”和“人OWNS之家”?我可以在这里使用任何已知的解决方案或解决方法吗?

python neo4j py2neo
2个回答
2
投票

问题是“Owns”被设置为与“Car”节点的关系。你需要建立另一种关系来拥有一所房子。如果您希望关系在Neo4j中具有“OWNS”标签,则需要填充RelatedTo函数的第二个变量。这将在第3章的Py2Neo文档(http://py2neo.org/v3/)中介绍。

class Person(GraphObject):
    name = Property()

    OwnsCar = RelatedTo("Car", "OWNS")
    OwnsHouse = RelatedTo("House" "OWNS")

class Car(GraphObject):
    model = Property()

class House(GraphObject):
    city = Property()

我想说Rick的答案解决了我试图用Py2Neo OGM标记的问题。谢谢里克!


1
投票

我基本上有同样的问题。我无法找到答案,并尝试使用py2neoneomodel提出解决方案。

只是一个初学者

值得注意的是,我绝对不会回答这些作为这些库中的任何一个库的专家,而是作为有人试图评估什么可能是开始一个简单项目的最佳人。

最终结果

最终的结果是我在py2neo中找到了一个似乎有效的解决方法。我也得到了neomodel的结果,我甚至更高兴。我最终对这两个图书馆感到有些沮丧,但发现neomodel对新手来说更直观。

资产标签是答案权吗?

我认为答案是创建一个“资产”标签并将此标签添加到House和Car并在Person和Asset之间创建[:OWNS]关系。容易吗?不,显然不是。可能有一个简单的答案,但我无法找到它。我在py2neo中工作的唯一解决方案是下拉到库的低级(而不是OGM)部分。

这是我在py2neo中所做的:

class Person(GraphObject):
    name = Property()

class Car(GraphObject):
    name = Property()
    model = Property()
    asset = Label("Asset")

class House(GraphObject):
    name = Property()
    city = Property()
    asset = Label("Asset")

g = graph

# Create Pete
p = Person()
p.name = "Pete"
g.push(p)

# Create Ferrari
c = Car()
c.name = "Ferrari"
c.asset = True
g.push(c)

# Create House
h = House()
h.name = "White House"
h.city = "New York"
h.asset = True
g.push(h)

# Drop down a level and grab the actual nodes
pn = p.__ogm__.node
cn = c.__ogm__.node

# Pete OWNS Ferrari (lower level py2neo)
ap = Relationship(pn, "OWNS", cn)
g.create(ap)

# Pete OWNS House (lower level py2neo)
hn = h.__ogm__.node
ah = Relationship(pn, "OWNS", hn)
g.create(ah)

# Grab & Print
query = """MATCH (a:Person {name:'Pete'})-[:OWNS]->(n)
           RETURN labels(n) as labels, n.name as name"""
data = g.data(query)
for asset in data:
    print(asset)

这导致:

{'name': 'White House', 'labels': ['House', 'Asset']}
{'name': 'Ferrari', 'labels': ['Car', 'Asset']}

Neomodel版本

py2neo似乎用类名做一些巧妙的技巧来做它的魔法,而库似乎从这个魔法中排除了标签。 (我希望我错了,但正如我所说,我无法解决它)。我决定尝试neomodel。

class Person(StructuredNode):
    name = StringProperty(unique_index=True)
    owns = RelationshipTo('Asset', 'OWNS')
    likes = RelationshipTo('Car', "LIKES")

class Asset(StructuredNode):
    __abstract_node__ = True
    __label__ = "Asset"
    name = StringProperty(unique_index=True)

class Car(Asset):
    pass

class House(Asset):
    city = StringProperty()

# Create Person, Car & House
pete = Person(name='Pete').save()
car = Car(name="Ferrari").save()
house = House(name="White House", city="Washington DC").save()

#Pete Likes Car
pete.likes.connect(car)

# Pete owns a House and Car
pete.owns.connect(house)
pete.owns.connect(car)

创建这些对象后,它们使用起来相对简单:

for l in pete.likes.all():
    print(l)

结果:

{'name': 'Ferrari', 'id': 385}

使用“抽象”关系,结果是该类型的对象,在本例中为Asset。

for n in pete.owns.all():
    print(n)
    print(type(n))

结果:

{'id': 389}
<class '__main__.Asset'>

似乎有一种方法可以将这些对象“膨胀”到所需类型,但我放弃了试图将其想象成仅仅使用Cypher。 (感谢一些帮助理解这个...)

下降到Cypher级别,我们得到了我们想要的东西:

query = "MATCH (a:Person {name:'Pete'})-[:OWNS]->(n) RETURN n"
results, meta = db.cypher_query(query)
for n in results:
    print(n)

结果:

[<Node id=388 labels={'Asset', 'Car'} properties={'name': 'Ferrari'}>]
[<Node id=389 labels={'Asset', 'House'} properties={'city': 'Washington DC', 'name': 'White House'}>]

结论

对于我想解决的许多问题,标签的概念非常直观。我发现py2neo对标签的处理令人困惑。您的解决方法可能是下拉到py2neo的“较低级别”。我个人认为neomodel语法更友好,建议检查出来。 HTH。

© www.soinside.com 2019 - 2024. All rights reserved.