Neo4j 返回图形数据库中的列表集

Neo4j 返回图形数据库中的列表集,neo4j,nested-lists,Neo4j,Nested Lists,这是我们的后续问题。如果该问题被删除或发生实质性变化,我将重复该导语: 我目前正在研究高等教育课程和其他类似实体的建模(MATH101、BIOL360、BSc等),我们正在研究的选项之一是图形数据库。除了理论上,我不熟悉图形数据库 该数据库的一个用例是查询课程中可能的路径;例如,回答“什么样的最低课程组合才能满足获得计算机科学荣誉学士学位的要求?”。有些要求很简单(资格要求你完成了Comp101、Math101和Comp201),有些要求提供了选项(要求你完成了80分的100级或以上“科学”论文

这是我们的后续问题。如果该问题被删除或发生实质性变化,我将重复该导语:

我目前正在研究高等教育课程和其他类似实体的建模(MATH101、BIOL360、BSc等),我们正在研究的选项之一是图形数据库。除了理论上,我不熟悉图形数据库

该数据库的一个用例是查询课程中可能的路径;例如,回答“什么样的最低课程组合才能满足获得计算机科学荣誉学士学位的要求?”。有些要求很简单(资格要求你完成了Comp101、Math101和Comp201),有些要求提供了选项(要求你完成了80分的100级或以上“科学”论文)

我发现我认为很有希望,但我真正想要的是能够返回一个列表列表,其中每个组件列表代表一个潜在的路径。但是我没有找到一种方法来生成这样的列表,所以我猜我在概念层面上出了点问题

我可以这样做的一种方法是使用一个循环来查看资格节点,获取一个可能的节点组合,递归地满足该节点的需求,然后移动到下一个可能的组合。作为一名数据库开发人员,使用循环进行基于集合的操作在理论上显然是可以解决的,这种想法让我晚上睡不着觉,因此我将竭尽全力避免这种讨厌的事情如何构造查询来构建这样一组集合?


我再次标记了Neo4J,因为我倾向于使用它(从我所知道的情况来看),它是最广为人知/使用最广泛的图形dbms(我对我之前的问题有一个非常优雅的解决方案,在这个问题上有效),但我也对其他数据库中的解决方案持开放态度(事实上,如果在最新的SQL Server产品中有可能,这可能是理想的,因为其他基础设施也在其中)。

概括一下我的评论:使用递归或循环应该是不必要的,使用列表也可能不是正确的方法。您应该使用一个好的面向图形的数据模型(这充分利用了关系并利用索引来启动查询)

为了说明这一点,下面的查询使用了一个相当简单的数据模型来构建一个学校的部分图表:

CREATE
  (sci:Area {name: 'Science'}),
  (hum:Area {name: 'Humanities'}),

  (bio:Department {name: 'Biology'})-[:IN_AREA]->(sci),
  (phy:Department {name: 'Physics'})-[:IN_AREA]->(sci),
  (che:Department {name: 'Chemistry'})-[:IN_AREA]->(sci),
  (eng:Department {name: 'English'})-[:IN_AREA]->(hum),
  (his:Department {name: 'History'})-[:IN_AREA]->(hum),
  (soc:Department {name: 'Sociology'})-[:IN_AREA]->(hum),

  (bioMaj:Major {name: 'Biology'})-[:IN_DEPT]->(bio),
  (phyMaj:Major {name: 'Physics'})-[:IN_DEPT]->(phy),

  (bio101:Course {id: 'Bio101', name: 'Introductory Biology', level: 101, credits: 3})   -[:IN_DEPT]->(bio),
  (che101:Course {id: 'Chem101', name: 'Introductory Chemistry', level: 101, credits: 4})-[:IN_DEPT]->(che),
  (phy101:Course {id: 'Phys101', name: 'Newtonian Physics', level: 101, credits: 5})     -[:IN_DEPT]->(phy),
  (phy201:Course {id: 'Phys201', name: 'Mechanics', level: 201, credits: 4})             -[:IN_DEPT]->(phy),
  (phy202:Course {id: 'Phys202', name: 'Elec & Mag', level: 202, credits: 4})            -[:IN_DEPT]->(phy),
  (eng101:Course {id: 'Eng101', name: 'Intro to Poetry', level: 101, credits: 3})        -[:IN_DEPT]->(eng),
  (eng102:Course {id: 'Eng102', name: 'Intro to Drama', level: 102, credits: 3})         -[:IN_DEPT]->(eng),
  (eng103:Course {id: 'Eng103', name: 'Intro to Fiction', level: 103, credits: 3})       -[:IN_DEPT]->(eng),
  (eng202:Course {id: 'Eng201', name: 'Medieval Literature', level: 201, credits: 4})    -[:IN_DEPT]->(eng),
  (his100:Course {id: 'Hist100', name: 'Global History', level: 100, credits: 3})        -[:IN_DEPT]->(his),
  (soc100:Course {id: 'Soc100', name: 'Intro to Sociology', level: 100, credits: 3})     -[:IN_DEPT]->(soc),

  (fred:Student {id: 123456, name: 'Fred Smith'})-[:HAS_MAJOR]->(bioMaj),
  (sue:Student  {id: 987654, name: 'Sue Jones'})-[:HAS_MAJOR]->(phyMaj),

  (fred)-[:ENROLLED_IN {year: 2017, term: 1, grade: 3.73}]->(bio101),
  (fred)-[:ENROLLED_IN {year: 2017, term: 1, grade: 3.62}]->(eng101),
  (fred)-[:ENROLLED_IN {year: 2017, term: 2, grade: 3.55}]->(che101),
  (fred)-[:ENROLLED_IN {year: 2017, term: 2, grade: 2.95}]->(eng102),
  (fred)-[:ENROLLED_IN {year: 2018, term: 1, grade: 3.13}]->(eng202),
  (fred)-[:ENROLLED_IN {year: 2018, term: 1, grade: 3.68}]->(phy101),
  (sue) -[:ENROLLED_IN {year: 2017, term: 1, grade: 3.55}]->(che101),
  (sue) -[:ENROLLED_IN {year: 2017, term: 1, grade: 3.66}]->(eng101),
  (sue) -[:ENROLLED_IN {year: 2017, term: 2, grade: 3.77}]->(phy201),
  (sue) -[:ENROLLED_IN {year: 2017, term: 2, grade: 3.44}]->(soc100),
  (sue) -[:ENROLLED_IN {year: 2018, term: 1, grade: 3.33}]->(eng202),
  (sue) -[:ENROLLED_IN {year: 2018, term: 1, grade: 3.22}]->(phy101);
假设有一项要求,即所有理科专业的学生必须在3门人文课程中取得3.0+的成绩,并且其中至少一门人文课程必须达到200+的水平

我们可以通过以下方式找到满足该要求的所有理科学生(例如,
Sue Jones
):

MATCH (a1:Area)<-[:IN_AREA]-()<-[:IN_DEPT]-()<-[:HAS_MAJOR]-(student)-[e:ENROLLED_IN]->(course)-[:IN_DEPT]->()-[:IN_AREA]->(a2:Area)
WHERE a1.name = 'Science' AND a2.name = 'Humanities' AND e.grade >= 3.0
WITH student, COLLECT(course) AS courses
WHERE SIZE(courses) >= 3 AND ANY(c IN courses WHERE c.level >= 200)
RETURN student;

概括一下我的评论:使用递归或循环应该是不必要的,使用列表也可能不是正确的方法。你应该使用一个好的面向图形的数据模型(它充分利用关系并利用索引来启动查询)

为了说明这一点,下面的查询使用了一个相当简单的数据模型来构建一个学校的部分图表:

CREATE
  (sci:Area {name: 'Science'}),
  (hum:Area {name: 'Humanities'}),

  (bio:Department {name: 'Biology'})-[:IN_AREA]->(sci),
  (phy:Department {name: 'Physics'})-[:IN_AREA]->(sci),
  (che:Department {name: 'Chemistry'})-[:IN_AREA]->(sci),
  (eng:Department {name: 'English'})-[:IN_AREA]->(hum),
  (his:Department {name: 'History'})-[:IN_AREA]->(hum),
  (soc:Department {name: 'Sociology'})-[:IN_AREA]->(hum),

  (bioMaj:Major {name: 'Biology'})-[:IN_DEPT]->(bio),
  (phyMaj:Major {name: 'Physics'})-[:IN_DEPT]->(phy),

  (bio101:Course {id: 'Bio101', name: 'Introductory Biology', level: 101, credits: 3})   -[:IN_DEPT]->(bio),
  (che101:Course {id: 'Chem101', name: 'Introductory Chemistry', level: 101, credits: 4})-[:IN_DEPT]->(che),
  (phy101:Course {id: 'Phys101', name: 'Newtonian Physics', level: 101, credits: 5})     -[:IN_DEPT]->(phy),
  (phy201:Course {id: 'Phys201', name: 'Mechanics', level: 201, credits: 4})             -[:IN_DEPT]->(phy),
  (phy202:Course {id: 'Phys202', name: 'Elec & Mag', level: 202, credits: 4})            -[:IN_DEPT]->(phy),
  (eng101:Course {id: 'Eng101', name: 'Intro to Poetry', level: 101, credits: 3})        -[:IN_DEPT]->(eng),
  (eng102:Course {id: 'Eng102', name: 'Intro to Drama', level: 102, credits: 3})         -[:IN_DEPT]->(eng),
  (eng103:Course {id: 'Eng103', name: 'Intro to Fiction', level: 103, credits: 3})       -[:IN_DEPT]->(eng),
  (eng202:Course {id: 'Eng201', name: 'Medieval Literature', level: 201, credits: 4})    -[:IN_DEPT]->(eng),
  (his100:Course {id: 'Hist100', name: 'Global History', level: 100, credits: 3})        -[:IN_DEPT]->(his),
  (soc100:Course {id: 'Soc100', name: 'Intro to Sociology', level: 100, credits: 3})     -[:IN_DEPT]->(soc),

  (fred:Student {id: 123456, name: 'Fred Smith'})-[:HAS_MAJOR]->(bioMaj),
  (sue:Student  {id: 987654, name: 'Sue Jones'})-[:HAS_MAJOR]->(phyMaj),

  (fred)-[:ENROLLED_IN {year: 2017, term: 1, grade: 3.73}]->(bio101),
  (fred)-[:ENROLLED_IN {year: 2017, term: 1, grade: 3.62}]->(eng101),
  (fred)-[:ENROLLED_IN {year: 2017, term: 2, grade: 3.55}]->(che101),
  (fred)-[:ENROLLED_IN {year: 2017, term: 2, grade: 2.95}]->(eng102),
  (fred)-[:ENROLLED_IN {year: 2018, term: 1, grade: 3.13}]->(eng202),
  (fred)-[:ENROLLED_IN {year: 2018, term: 1, grade: 3.68}]->(phy101),
  (sue) -[:ENROLLED_IN {year: 2017, term: 1, grade: 3.55}]->(che101),
  (sue) -[:ENROLLED_IN {year: 2017, term: 1, grade: 3.66}]->(eng101),
  (sue) -[:ENROLLED_IN {year: 2017, term: 2, grade: 3.77}]->(phy201),
  (sue) -[:ENROLLED_IN {year: 2017, term: 2, grade: 3.44}]->(soc100),
  (sue) -[:ENROLLED_IN {year: 2018, term: 1, grade: 3.33}]->(eng202),
  (sue) -[:ENROLLED_IN {year: 2018, term: 1, grade: 3.22}]->(phy101);
假设有一项要求,即所有理科专业的学生必须在3门人文课程中取得3.0+的成绩,并且其中至少一门人文课程必须达到200+的水平

我们可以通过以下方式找到满足该要求的所有理科学生(例如,
Sue Jones
):

MATCH (a1:Area)<-[:IN_AREA]-()<-[:IN_DEPT]-()<-[:HAS_MAJOR]-(student)-[e:ENROLLED_IN]->(course)-[:IN_DEPT]->()-[:IN_AREA]->(a2:Area)
WHERE a1.name = 'Science' AND a2.name = 'Humanities' AND e.grade >= 3.0
WITH student, COLLECT(course) AS courses
WHERE SIZE(courses) >= 3 AND ANY(c IN courses WHERE c.level >= 200)
RETURN student;

事实上,我正在考虑删除它,因为我现在还不完全相信,在没有递归或循环的情况下,在概念上实现这一点是可能的……我不认为使用递归或循环是必要的,使用列表也可能不是正确的方法。在我看来,您只需要一个好的面向图形的数据模型(这很好地利用了关系并利用索引来启动查询)。这里的列表要求听起来更像输出。您可以使用
collect()
在查询中以列表的形式收集内容,根据查询的不同,您可以使用
collect())
再次谈到集合。我认为更重要的是要为此建立一个好的模型,包括表达需求的方式或逻辑。事实上,我正在考虑删除这一点,因为我现在还不完全相信在概念上不使用递归或循环就可以实现这一点……我不认为使用递归n或循环是必要的,使用列表也可能不是正确的方法。在我看来,您只需要一个良好的面向图形的数据模型(它充分利用关系并利用索引来启动查询)。这里的列表要求听起来更像输出。您可以使用
collect()
在查询中以列表形式收集内容,根据查询的不同,可以使用
collect()
再次谈到集合。不过,我认为更重要的是要为此找到一个好的模型,包括表达需求的方式或分叉需求的逻辑。这是非常了不起的,谢谢你,我再一次被图形与关系的不同思维方式所震撼。我将不得不花一点时间来理解消化这一点,所以当我完成这一过程后,我会接受:)这是非常了不起的,谢谢你,我的头脑再一次被图形思维方式与关系思维方式的不同所打动。我将不得不花一点时间来消化这一点,所以当我完成这一过程后,我会接受:)