在neo4j中同时创建节点和关系

16

我正在尝试使用Neo4j构建一个包含七种不同类型节点的结构的数据库,总共大约有4-5000个节点和40000个关系。我目前正在使用的Cypher代码是首先使用以下代码创建节点:

Create (node1:type {name:'example1', type:'example2'})

大约有4000个具有独特节点的示例。

然后我得到了以下关系说明:

Create
(node1)-[:r]-(node51),
(node2)-[:r]-(node5),
(node3)-[:r]-(node2);

大约有40000种这样独特的关系。

对于规模较小的图表,这一点都不成问题。但对于这个图表,执行查询永远不会停止加载。

有什么建议可以让我让这种类型的查询起作用吗?或者我应该做些什么呢?

编辑。我正在尝试构建一个关于产品的大型图形,其中包含其发布、发布版本、功能等。与电影图例类似。

该产品总共有大约6个发布版本,每个发布版本大约有20个发布版本。总共有371个功能,其中371个功能中还有438个功能版本。每个发布版本(总共120个)则有大约2-300个功能版本。这些功能版本被映射到其具有依赖关系的功能,这些依赖关系涉及数据库中的各个方面。我还涉及了硬件依赖性,例如可能运行这些功能的硬件、发行版等。因此,我使用像下面这样的 Cypher 代码:

Create (Product1:Product {name:'ABC', type:'Product'})
Create (Release1:Release {name:'12A', type:'Release'})
Create (Release2:Release {name:'13A, type:'release'})
Create (ReleaseVersion1:ReleaseVersion {name:'12.0.1, type:'ReleaseVersion'})
Create (ReleaseVersion2:ReleaseVersion {name:'12.0.2, type:'ReleaseVersion'})    

并且在它们下面,我使用了结构化的方式进行了整理

Create (Product1)<-[:Is_Version_Of]-(Release1),
(Product1)<-[:Is_Version_Of]-(Release2),
(Release2)<-[:Is_Version_Of]-(ReleaseVersion21),        

一直到特性层面,我还添加了它们之间的依赖关系,例如:

(Feature1)-[:Requires]->(Feature239),
(Feature239)-[:Requires]->(Feature51);       

由于我需要从许多不同的Excel表格等文件中找到所有这些信息,所以我以这种方式编写了代码,认为我可以将其合并为一个大的Cypher查询,并在本地主机上的/浏览器上运行它。只要我一次不使用超过4-5000个查询,它就非常好用。然后,在最长5-10秒的时间内创建整个数据库,但现在当我尝试同时运行约45000个查询时,它已经运行了近24小时,仍在加载并显示“执行查询...”。我想知道是否有任何方法可以改善它所需的时间?数据库最终会被创建吗?还是我可以做一些更智能的索引或其他事情来提高性能?因为按照我的Cypher编写方式,我不能将其分成几部分,因为数据库中的每个内容都与产品有某种连接。我需要重新编写代码吗,还是有其他的解决办法?


还要看一下MERGE子句 https://neo4j.com/docs/developer-manual/current/cypher/clauses/merge/ - Tony
5个回答

24
你可以使用单个创建语句创建多个互相链接的节点和关系,就像这样:

create (a { name: "foo" })-[:HELLO]->(b {name : "bar"}),
       (c {name: "Baz"})-[:GOODBYE]->(d {name:"Quux"});

因此,这是一种方法,而不是使用单个语句创建每个节点,然后使用单个语句创建每个关系。

您还可以通过先匹配再创建来从对象创建多个关系:

match (a {name: "foo"}), (d {name:"Quux"}) create (a)-[:BLAH]->(d);

当然,你可以有多个匹配子句和多个创建子句。

你可能会尝试匹配给定类型的节点,然后从该类型的节点创建所有必要的关系。由于您拥有足够的关系,这将需要许多查询。确保您已经索引了用于匹配节点的属性。随着您的数据库变得越来越大,这将是重要的,以便快速查找您试图创建新关系的内容。

您没有指定哪个查询不会“停止加载”。使用具体信息更新您的问题,并告诉我们您已经尝试过什么,也许我们可以提供帮助。


这里不需要括号吗?(a)-[:BLAH]->(b) - orestiss
2
是的。这个答案是在2014年写的,当时你不需要它们。 - FrobberOfBits

12

如果您已经创建了其中一个节点,则简单的方法是:

MATCH (n: user {uid: "1"}) CREATE (n) -[r: posted]-> (p: post {pid: "42", title: "Good Night", msg: "Have a nice and peaceful sleep.", author: n.uid});

在这里,用户节点已经存在,您创建了一个新的关系和一个新的帖子节点。


嗨@Ashwin,我们如何在上面的查询中提供标签?如果我想将帖子节点的字段值作为默认标签,我们该怎么做? - Tirupati Singh

1

可以使用单个密码查询来创建一个新节点并将其与现有节点相关联。

例如,假设您从以下内容开始:

  • 一个现有的“ One”节点,它具有“ id”属性“ 1”

而您的目标是:

  • 创建第二个节点,我们称之为“ Two”,它应该具有属性id:“2”
  • 将两个节点关联在一起

您可以使用一个单独的Cypher查询来实现这个目标,如下所示:

MATCH (one:One {id:'1'})
CREATE (one) -[:RELATED_TO]-> (two:Two {id:'2'})

似乎只有在将其更改为 MATCH (one:One) WHERE id(one)=1 ... 时才能正常工作,但还是谢谢回答。 - Yan King Yin
你使用的是哪个版本的Neo4j?也许随着时间的推移,他们已经改变了这种行为。我相信我在我的帖子回答中使用了4.4.5版本。 - Kaan
Neo4j桌面版1.5.0,DBMS 4.4.11。哦,也许我漏掉了对'1'的引号? - Yan King Yin

1

1
如果您能使用Neo4j 2.1预发布版本,那么您应该尝试使用新的LOAD CSVPERIODIC COMMIT功能。它们专为这种用例而设计。 LOAD CSV允许您使用一个或多个Cypher模式描述数据结构,同时提供CSV中的值以避免重复。 PERIODIC COMMIT可以帮助使大型导入更加可靠,并通过减少所需内存的数量来提高性能。

这看起来是一件非常有趣的事情,我的唯一问题是我是否可以使用例如特征和特征之间的关系,并且在它们之间有不同类型的关系,因为在这个数据库中,相同类型的节点可能有十种不同的关系。因此,我不能使用例如: CREATE (p)-[:PLAYED { role: csvLine.role }]->(m)或者我能否一次运行一部分我的数据库?因为这可能是我当前的问题,我无法将其分成更小的部分。 - ErikOstergren
关系类型、标签和属性名称必须在查询中明确指定 - 关系类型不能来自CSV文件。相反,您通常会使用一个CSV文件和一个查询来处理每种类型。 - Andres

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接