【问题标题】:GraphDB: Node as a property of a relationshipGraphDB:节点作为关系的属性
【发布时间】:2020-04-23 19:17:24
【问题描述】:

我正在尝试分析 graphDB 作为 RDBMS 的替代方案来解决问题域。这是我试图解决的问题的类比。

P:MichaelP:Angela r:like_to_eat G:AppleG:面包G:AppleG:Breadr:available_in S:WalmartS:Whole Foods 。 到目前为止,它很简单。这是一张我认为最能表达图表的图像。

问题在于,当我试图指明安吉拉喜欢 Whole Foods 的 Apples 和 Walmart 的 Bread 时。迈克尔喜欢吃沃尔玛的苹果和全食超市的面包。我怎样才能在图表中表示类似的东西?听起来我需要超图的概念才能解决这个问题,但我也听说任何超图问题也可以用属性图来解决。可以使用 Neo4j 或 CosmosDB 等标准图形解决方案来解决这个问题吗?有人可以帮我解决这个问题吗

【问题讨论】:

  • 我删除了特定于产品的标签,因为这是一个相当通用的图表问题。此外,我相信您会发现任何图形数据库都会支持您尝试创建的内容,但使用不同的解决方案。我会专注于关于特定数据库引擎的特定问题。

标签: graph-databases


【解决方案1】:

您可以在Preference 节点(例如)中“具体化”三向关系(PersonGroceryStore),从而生成如下数据模型:

在 neo4j 中,您可以使用此 Cypher 查询来表示“Angela 喜欢 Whole Foods 的 Apples 和 Walmart 的 Bread”:

MERGE (angela:Person {name: 'Angela'})
MERGE (apple:Grocery {name: 'Apple'})
MERGE (bread:Grocery {name: 'Bread'})
MERGE (wf:Store {name: 'Whole Foods'})
MERGE (wm:Store {name: 'Walmart'})
CREATE
  (angela)-[:LIKES]->(pref1:Preference),
  (pref1)-[:ITEM]->(apple),
  (pref1)-[:AT_STORE]->(wf),
  (angela)-[:LIKES]->(pref2:Preference),
  (pref2)-[:ITEM]->(bread),
  (pref2)-[:AT_STORE]->(wm)

【讨论】:

  • 这是有道理的@cybersam。这几乎就像稍微调整数据模型以确保边只有 2 个顶点。谢谢。
  • cybersam:您对@venegr 下面的建议有何看法?我觉得以这种方式对图表进行建模会让事情变得更容易,但我不确定哪种方法会在性能方面做得更好。
  • 在 neo4j 中,通常不建议在关系中存储 nodeId,因为您需要做更多工作来查找引用的节点。此外,朝相反的方向发展(例如,试图找到喜欢某家商店的每个人)也需要更多的工作。
【解决方案2】:

另一种选择是将“Angela likes Apples from Whole Foods”中的“Whole Foods”表示为边缘“喜欢吃”的属性,这成为真正的“属性图”。这是数据模型:

在 Nebula Graph(这是一个图数据库解决方案)中,您可以使用以下 nGQL 查询进行建模:

// Define the schema
create tag person(name string)
create tag grocery(name string)
create tag store(name string)
create edge likes(storeID int)
create edge sells()

// Insert the vertices
INSERT VERTEX person(name) VALUES 100:("Michael");
INSERT VERTEX person(name) VALUES 101:("Angela");
INSERT VERTEX grocery(name) VALUES 200:("Apple");
INSERT VERTEX grocery(name) VALUES 201:("Bread");
INSERT VERTEX store(name) VALUES 300:("Walmart");
INSERT VERTEX store(name) VALUES 301:("Whole Foods");


// Insert the edges
INSERT EDGE likes(storeID) VALUES 101->200:(301);
INSERT EDGE likes(storeID) VALUES 101->201:(300);
INSERT EDGE sells() VALUES 300->200:();
INSERT EDGE sells() VALUES 300->201:();
INSERT EDGE sells() VALUES 301->200:();
INSERT EDGE sells() VALUES 301->201:();

查找安吉拉喜欢哪家商店的苹果

> GO FROM 101 OVER likes where likes._dst==200 YIELD likes.storeID as storeID | FETCH PROP ON store $-.storeID

找出安吉拉在沃尔玛喜欢多少杂货

> GO FROM 101 OVER likes WHERE likes.storeID = 300

希望对您有所帮助。

【讨论】:

  • 对于这种方法,当我想查询边/顶点的属性时,你知道性能是如何受到影响的吗?
  • @MichaelScott 如果要获取特定节点或边的属性,则为 O(1)。 Nebula Graph 采用 KV 存储。对于顶点和边,属性都是值部分。参考存储设计github.com/vesoft-inc/nebula/blob/master/docs/manual-EN/…如果你没有特定的节点或边,例如要查找价格高于 1 的杂货,您可以为此属性创建索引。 docs.nebula-graph.io/manual-EN/2.query-language/…
  • 不建议将nodeID用作属性的原因是nodeID是默认的内部属性,一旦删除就会重新分配。在 Nebula Graph 中,nodeID 是由用户生成的,这就是为什么使用 nodeID 作为边属性没有问题的原因。要找到喜欢特定商店的每个人,请使用反向查询“从 300 开始销售收益 sells._dst as groceries | go from $-.groceries over likes reversely yield likes._dst”。总复杂度为 o(m) + o(m*k)。在 Nebula Graph 中,对于单个节点,入边和出边都存储在与节点相同的主机上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
相关资源
最近更新 更多