我们应该使用特定于节点的关系还是与节点无关的关系?

时间:2013-11-27 14:39:55

标签: neo4j cypher spring-data-neo4j

我尝试连接Spring Data Neo4j中的各种节点类型。 是否建议(或不鼓励)对链接不同节点类型的类似关系使用相同的关系类型?

例如,如果我们有一个Driver类(注释为@NodeEntity),我们想要模拟驱动程序可以驱动不同车辆的事实,例如汽车和自行车,这是更好的:

@RelatedTo(elementClass = CarNode.class, type = "drives", direction = OUTGOING)
private Set<Car> cars;

@RelatedTo(elementClass = BikeNode.class, type = "drives", direction = OUTGOING)
private Set<Bike> bikes;

因为司机可以驾驶不同类型的车辆,或者我们应该在关系中指出车辆的类型:

@RelatedTo(elementClass = CarNode.class, type = "drivesCar", direction = OUTGOING)
private Set<Car> cars;

@RelatedTo(elementClass = BikeNode.class, type = "drivesBike", direction = OUTGOING)
private Set<Bike> bikes;

第一种可能性似乎在语义上更正确,但在整个图中使用特定关系可以允许更快的遍历(不需要测试节点类型)似乎是合乎逻辑的。

如果通用关系更好,那么如何使用Cypher查询获得一组汽车或仅一组自行车?

谢谢!

2 个答案:

答案 0 :(得分:2)

一般来说,建议对关系类型进行详细说明。

主要原因是您的查询会变得更便宜。例如,假设您想要查询给定的驱动程序他开的所有自行车。如果是通用关系类型drives,则会在Cypher中解决:

start d=node:driver(name=<driverName>)
match (d)-[:drives]->(vehicle)
where vehicle.__type__ = 'Bike'
return vehicle

而在详细关系类型的情况下:

start d=node:driver(name=<driverName>)
match (d)-[:drivesBike]->(bike)
return bike

第二个更便宜,因为你没有穿越非自行车。在第一种情况下,你对遍历贪婪,然后应用过滤器。

答案 1 :(得分:2)

为Stefan的回答添加一点:您实际上可能会考虑同时使用通用drives drivesBike&amp; drivesCar.在某些情况下,您可能只想检索一个人驾驶的所有车辆,为此......您有drives.如果您想要所有骑自行车的人,那么drivesBike.如果您同时具有特定和通用关系,则可以以两种方式进行最佳查询,并且具有额外关系并不会真正影响您的数据库大小(尽管它在代码方面添加了一些内容,以添加两个关系链接。请记住,如果您只有特定的驱动程序关系,则会有一些OR查询,所有驱动程序类型都被调出,并且每次添加新的车辆类型时都需要更新查询。例如,拥有通用drives关系会更方便。

实际上在Graph Databases一书中提到了这个想法。您可以在那里阅读有关此模式的更多信息。