匹配多表优化Neo4j

时间:2018-09-30 06:43:21

标签: neo4j cypher graph-databases

我在Neo4j数据库中有3个带有标签的节点-应用程序,电话通讯录,短信。 我正在尝试编写类似的联系人和短信中的名称将检索所有应用程序ID的查询。 但是,我编写的查询执行了一段时间,并由于堆减少的错误而崩溃。 如何优化查询?

MATCH (pcb:PhoneContactsBook {phone: pcb.phone})-[:APP_PCB]->
      (a:Applications)-[:APP_SMS]->
      (sms:Sms {address: sms.address}) 
RETURN distinct pcb.phone, 
       collect(a.application_id);

我试图在用于过滤的字段(例如sms.address)上设置索引,但是它与它们的运行时间甚至更长。

这是查询计划: enter image description here

1 个答案:

答案 0 :(得分:2)

@stdob指出,MATCH子句中的以下两个节点模式没有任何意义(很可能是导致崩溃的原因):

(pcb:PhoneContactsBook {phone: pcb.phone})

(sms:Sms {address: sms.address}) 

第一个节点模式正在寻找PhoneContactsBook值等于自身的phone节点,第二个节点模式正在寻找Sms值等于自身的address节点本身。由于这些模式将匹配所有PhoneContactsBookSms节点(只要它们分别具有phoneaddress属性),因此您的MATCH子句最终会完成以下代码段的较昂贵版本,该代码段根本不按电话号码或地址进行过滤:

MATCH (pcb:PhoneContactsBook)-[:APP_PCB]->(a:Applications)-[:APP_SMS]->(sms:Sms)

因此,您的查询可能会导致大量匹配,这需要很长时间,并最终导致数据库用完堆。

您尚未提供有关数据模型的足够信息,让我知道如何解决此问题。但是,如果我正确地假设一个PhoneContactsBook节点包含一个address属性,而一个Sms节点包含一个phone属性,也许您是说以下意思?

MATCH (pcb:PhoneContactsBook {phone: sms.phone})-[:APP_PCB]->
      (a:Applications)-[:APP_SMS]->
      (sms:Sms {address: pcb.address}) 
RETURN distinct pcb.phone, 
       collect(a.application_id);

顺便说一句,您应该使用正确的术语。由于neo4j是图数据库,因此它没有“表”。相反,ApplicationsPhoneContactsBookSms是节点“标签”。