Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Neo4j:关于如何使用共享节点对图形建模的建议,但基于某些属性具有唯一路径_Java_Neo4j_Graph Databases - Fatal编程技术网

Java Neo4j:关于如何使用共享节点对图形建模的建议,但基于某些属性具有唯一路径

Java Neo4j:关于如何使用共享节点对图形建模的建议,但基于某些属性具有唯一路径,java,neo4j,graph-databases,Java,Neo4j,Graph Databases,我正在尝试为我正在开发的应用程序建立数据模型。该应用程序当前正在使用Neo4j 基本模型有三种类型:课程、测试、问题。该应用程序允许用户创建课程,然后将测试(现有或新测试)与课程关联。然后,他们可以在测试中添加或删除问题,但此添加和删除不应影响图表中的其他课程/测试 以下是我考虑过的各种模式,它们各有利弊: 1.)创建课程节点,测试节点的边缘,然后在测试问题上创建/删除问题的边缘,边缘上具有课程id的属性。使用此模型,密码查询如下所示: match(c:COURSE{id:'123})(q:QU

我正在尝试为我正在开发的应用程序建立数据模型。该应用程序当前正在使用Neo4j

基本模型有三种类型:课程、测试、问题。该应用程序允许用户创建课程,然后将测试(现有或新测试)与课程关联。然后,他们可以在测试中添加或删除问题,但此添加和删除不应影响图表中的其他课程/测试

以下是我考虑过的各种模式,它们各有利弊:

1.)创建课程节点,测试节点的边缘,然后在测试问题上创建/删除问题的边缘,边缘上具有课程id的属性。使用此模型,密码查询如下所示:

match(c:COURSE{id:'123})(q:QUESTION)其中r.courseId='123'返回c,t,q

优点:简单的数据模型。最明显的解决办法

缺点:在两个节点之间经过几百条边后,性能确实会受到影响,因为从课程到问题没有一条简单的路径,它需要评估/比较所有边

2.)创建课程节点,即测试节点的边缘,然后对于测试和问题之间的边缘,使用课程id作为边缘的类型。使用此模型,cypher查询将如下所示:

match(c:COURSE{id:'123'})(q:QUESTION)返回c,t,q

优点:根据我的研究,Neo4j似乎能更好地处理这种类型的建模

缺点:边缘类型的数量有上限吗?不确定如果有成百上千的课程,其表现是否会比#1更好

3.)创建课程节点、测试节点的一条边,以及使用课程ID列表创建一条边。使用此模型,cypher查询将如下所示:

match(c:COURSE{id:'123'})(q:QUESTION),其中r.courseIds包含'123'返回c,t,q(不是正确的语法,但你明白了)

优点:看起来还是很简单

缺点:不确定cypher是否支持这种类型的查询。扫描单个边缘的属性列表是否与扫描具有单个属性的所有边缘一样糟糕

4.)为每门课程创建测试和问题的副本

优点:似乎是目前为止最快的解决方案,因为只有一条路径,不需要比较。从课程开始,遍历整个图表

缺点:这将导致大量冗余数据。似乎这会破坏使用图形的目的,可以在Cassandra或其他数据存储中更好地建模

5.???-寻找我错过的任何其他建议

基本上,我正在寻找的是创建具有共享节点的图的最佳方法,但它具有基于某些属性的唯一路径,其中性能不在完成大量可能属性值的遍历所需的分钟数上。

注:

  • 我只实现了#1,因此我发现在创建了几百个课程之后,查询的性能非常糟糕
  • 我试图在提问时尽可能清晰完整,但如果我遗漏了什么,请要求澄清
  • 我已经做了很多研究,但我还没有找到一个很好的建模方法

我认为不需要在多个位置存储课程ID,然后在以后查询匹配的ID

这里有一个更简单的模型,对我来说更有意义。每个
测试
节点都与单个
课程
节点相关,并且与多个问题节点相关

要查找单个课程的每个测试(及其问题集合),查询如下所示:

MATCH (c:Course {id:'123'})<-[:FOR]-(t:Test)-[:HAS_QUESTION]->(q:Question)
RETURN c, t, COLLECT(q) AS questions;
MATCH(c:Course{id:'123'})(问题)
返回c、t、收集(q)作为问题;

单一测试不应该只与单一课程关联吗?感谢您的回复。这要简单得多,但并不能完全解决问题。在您的示例中,当我们创建课程节点时,还需要创建一个新测试(或多个测试)。我试图简化提出这个问题的模式。有一个针对不同类型课程的“硕士”课程,包括测试和已经定义的问题。创建新课程时,我们会制作一份与先前存在的测试和问题相关的硕士(即课程节点)副本。然后,用户可以根据需要修改这些测试和问题。在您的解决方案中,我们必须为每门课程创建一份测试副本。这或多或少类似于原始问题中的#4。注意:用户只能操作关系,而不能操作节点的实际值,因此任何类型的复制都会导致重复数据。如果可能的话,我想通过改变边缘来实现这一点……为什么只操纵关系会受到限制?这确实会妨碍找到合理的解决办法。你甚至可以创建节点吗?