Neo4j 创建以下匹配语句最有效的方法是什么?为什么?
问题:Neo4j 创建以下匹配语句最有效的方法是什么?为什么?,neo4j,cypher,Neo4j,Cypher,问题: 创建以下MATCH语句最有效的方法是什么?为什么 详细问题: 假设我们有一个Place节点,该节点具有可变数量的属性,并且需要根据其类别从潜在的数十亿个节点中查找节点。我正试图了解每个查询的性能,结果证明这是相当困难的 可能的查询: 使用属性查找匹配放置节点: 匹配(实体:地点{category:“Food”}) 将Place节点与isCategory关系与Food节点匹配: 匹配(实体:地点)-[:isCategory]->(类别:食品) 将位置节点与食品关系匹配到类别节点: 匹配(
创建以下
MATCH
语句最有效的方法是什么?为什么
详细问题:假设我们有一个
Place
节点,该节点具有可变数量的属性,并且需要根据其类别从潜在的数十亿个节点中查找节点。我正试图了解每个查询的性能,结果证明这是相当困难的
可能的查询:- 使用
属性
查找匹配
放置
节点:
匹配(实体:地点{category:“Food”})
- 将
节点与Place
关系与isCategory
节点匹配:Food
匹配(实体:地点)-[:isCategory]->(类别:食品)
- 将
节点与位置
关系匹配到食品
节点:类别
匹配(实体)-[类别:食品]->(:类别)
- 将
节点与Food
与iscategorifFor
节点的关系匹配:Place
MATCH(类别:食品)-[:isCategoryFor]->(实体:地点)
MATCH (c:Category) WHERE c.name = "Bar" OR c.name = "Food", (c)<-[:IS_A]-(p:Place)
RETURN p
更复杂:让我们稍微复杂一点,假设我们现在需要使用多个类别查找所有
Place
节点。例如:查找具有类别食品或条形图的所有Place
节点
我们能不能再加上一个MATCH
语句?如果没有,在这里最有效的路线是什么
额外:
是否有工具可以帮助我描述遍历过程并告诉我选择的最佳方法?如果我正确理解您的域,我建议将您的类别
设置为节点本身
MERGE (:Category {name:"Food"})
MERGE (:Category {name:"Bar"})
MERGE (:Category {name:"Park"})
并将每个位置
节点连接到它所属的类别
MERGE (:Place {name:"Central Park"})-[:IS_A]->(:Category {name:"Park"})
MERGE (:Place {name:"Joe's Diner"})-[:IS_A]->(:Category {name:"Food"})
MERGE (:Place {name:"Joe's Diner"})-[:IS_A]->(:Category {name:"Bar"})
然后,如果您想查找属于类别的位置
,它可以非常快速。首先匹配类别,然后扩展到与该类别相关的位置
MATCH (c:Category {name:"Bar"}), (c)<-[:IS_A]-(p:Place)
RETURN p
或者更好的是,对类别名称使用唯一性约束,这将索引它们并防止重复
CREATE CONSTRAINT ON (c:Category) ASSERT c.name IS UNIQUE
索引(和唯一性)对查询速度有很大影响
为什么这是最快的
Neo4j以非常紧凑、快速访问的格式存储节点和关系。一旦你有了一个节点或关系,获得相邻的关系或节点是非常快的。但是,它分别存储每个节点(和关系)的属性,这意味着查看属性的速度相对较慢
目标是尽快到达起始节点。一旦到达那里,遍历相关实体就很快了。如果你只有1000个类别,但你有10亿个位置,那么挑选一个类别
比挑选一个位置
更快。一旦有了起始节点,就可以非常高效地访问相关节点
其他选项
只是想强调一下,这是让你的其他选择变得更慢或更糟的原因
在第一个示例中,您正在查看每个节点上的属性以查找匹配项。属性查找速度很慢,而且您正在执行十亿次。索引可以帮助实现这一点,但仍然需要大量的工作。此外,您在每个十亿个地点有效地复制了类别数据,而没有利用Neo4j的优势
在所有其他示例中,您的数据模型似乎都很奇怪。“食品”、“酒吧”、“公园”等都是类别的实例,而不是单独的类型。它们都应该是自己的节点,但它们都应该有类别
标签,因为它们就是这样。此外,类别是事物,因此它们应该是节点。关系描述事物之间的联系。以这种方式使用类别是没有意义的
我希望这有帮助 如果我正确理解您的域,我建议将您的类别
设置为节点本身
MERGE (:Category {name:"Food"})
MERGE (:Category {name:"Bar"})
MERGE (:Category {name:"Park"})
并将每个位置
节点连接到它所属的类别
MERGE (:Place {name:"Central Park"})-[:IS_A]->(:Category {name:"Park"})
MERGE (:Place {name:"Joe's Diner"})-[:IS_A]->(:Category {name:"Food"})
MERGE (:Place {name:"Joe's Diner"})-[:IS_A]->(:Category {name:"Bar"})
然后,如果您想查找属于类别的位置
,它可以非常快速。首先匹配类别,然后扩展到与该类别相关的位置
MATCH (c:Category {name:"Bar"}), (c)<-[:IS_A]-(p:Place)
RETURN p
或者更好的是,对类别名称使用唯一性约束,这将索引它们并防止重复
CREATE CONSTRAINT ON (c:Category) ASSERT c.name IS UNIQUE
索引(和唯一性)对查询速度有很大影响
为什么这是最快的
Neo4j以非常紧凑、快速访问的格式存储节点和关系。一旦你有了一个节点或关系,获得相邻的关系或节点是非常快的。但是,它分别存储每个节点(和关系)的属性,这意味着查看属性的速度相对较慢
目标是尽快到达起始节点。一旦到达那里,遍历相关实体就很快了。如果你只有1000个类别,但你有10亿个位置,那么挑选一个类别
比挑选一个位置
更快。一旦有了起始节点,就可以非常高效地访问相关节点
其他选项
只是想强调一下,这是让你的其他选择变得更慢或更糟的原因
在第一个示例中,您正在查看每个节点上的属性以查找匹配项。属性查找速度很慢,而且您正在执行十亿次。索引可以帮助实现这一点,但仍然需要大量的工作。此外,您还可以有效地复制