py2neo ogm与多节点标签的关系

时间:2016-09-02 12:14:39

标签: python neo4j py2neo

我想使用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)

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

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

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

这导致:

Car
Car

此行为与类对象一致。

我如何塑造"人OWNS汽车"和#34;人OWNS House"在py2neo.ogm中使用相同的类?我可以在这里使用任何已知的解决方案或解决方法吗?

2 个答案:

答案 0 :(得分: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 :(得分: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'>

似乎有一种方法可以“膨胀”#34;这些对象达到了理想的类型,但我放弃了试图将其用于支持使用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对标签的处理令人困惑。您的解决方法可能是下降到&#34;较低级别&#34; py2neo。我个人认为neomodel语法更友好,建议检查出来。 HTH。