为了在Neo4j查询中获得最佳的遍历速度,我们应该使关系类型尽可能具体

让我们看一下几周前我在Skillsmatter上发表的“ 建模建议引擎建模 ”演讲中的一个例子。

我需要决定如何为成员事件之间的“ RSVP”关系建模。 一个人可以对事件表示“是”或“否”,我想同时捕捉这两个响应。

即我们可以选择:

和:

在确定模型时,我们主要需要考虑我们要编写的查询的类型。 我们不应该忘记更新模型,但是根据我的经验,查询图要比更新它们花费更多的时间。

让我们依次看一下其中的每个:

我们要写什么查询?

第一个查询将使用以前的“是” RSVP作为将来事件的关注指标。 我们对此查询的“否” RSVP不感兴趣。

我从具有“ response”属性的通用RSVP关系类型开始,以区分“是”和“否”:

MATCH (member:Member {name: "Mark Needham"})
MATCH (futureEvent:Event) WHERE futureEvent.time >= timestamp()
MATCH (futureEvent)<-[:HOSTED_EVENT]-(group)OPTIONAL MATCH (member)-[rsvp:RSVPD {response: "yes"}]->(pastEvent)<-[:HOSTED_EVENT]-(group)
WHERE pastEvent.time < timestamp()RETURN group.name, futureEvent.name, COUNT(rsvp) AS previousEvents
ORDER BY  previousEvents DESC

这运行得相当快,但是我很好奇是否可以通过更改为更具体的模型来使查询更快地运行。 使用更具体的关系类型,我们的查询显示为:

MATCH (member:Member {name: "Mark Needham"})
MATCH (futureEvent:Event) WHERE futureEvent.time >= timestamp()
MATCH (futureEvent)<-[:HOSTED_EVENT]-(group)OPTIONAL MATCH (member)-[rsvp:RSVP_YES]->(pastEvent)<-[:HOSTED_EVENT]-(group)
WHERE pastEvent.time < timestamp()RETURN group.name, futureEvent.name, COUNT(rsvp) AS previousEvents
ORDER BY  previousEvents DESC

现在,我们可以分析查询并比较两个解决方案的数据库匹配:

RSVPD {response: "yes"}
Cypher version: CYPHER 2.3, planner: COST. 688635 total db hits in 232 ms.RSVP_YES
Cypher version: CYPHER 2.3, planner: COST. 559866 total db hits in 207 ms.

因此,通过使用更具体的关系类型,我们会获得一点收益。 数据库命中率较低的原因部分是因为我们不再需要在每个“ RSVP”属性上查找“ response”属性并检查其是否与“ yes”匹配。 我们还评估了较少的关系,因为我们只查看正向的RSVP,负向的被忽略。

我们的下一个查询可能是捕获成员发出的所有RSVP,并在事件旁边列出它们:

MATCH (member:Member {name: "Mark Needham"})-[rsvp:RSVPD]->(event)
WHERE event.time < timestamp()
RETURN event.name, event.time, rsvp.response
ORDER BY event.time DESC
MATCH (member:Member {name: "Mark Needham"})-[rsvp:RSVP_YES|:RSVP_NO]->(event)
WHERE event.time < timestamp()
RETURN event.name, event.time, CASE TYPE(rsvp) WHEN "RSVP_YES" THEN "yes" ELSE "no" END AS response
ORDER BY event.time DESC

再次,我们看到了更具体的关系类型的少量数据库命中率:

RSVPD {response: "yes"} / RSVPD {response: "no"}
Cypher version: CYPHER 2.3, planner: COST. 684 total db hits in 37 ms.RSVP_YES / RSVP_NO
Cypher version: CYPHER 2.3, planner: COST. 541 total db hits in 24 ms.

但是,查询非常麻烦,除非我们将响应存储为关系的属性,否则返回“ yes”或“ no”的代码会有些尴尬。 如果引入了我们选择排除的“ waitlist” RSVP,则更具体的方法查询将变得更加痛苦。

我们需要更新关系吗?

是! 用户可以在事件发生之前更改其RSVP,因此我们需要能够进行处理。

让我们看一下使用两种模型处理RSVP更改时必须编写的查询:

通用关系类型

MATCH (event:Event {id: {event_id}})
MATCH (member:Member {id: {member_id}})
MERGE (member)-[rsvpRel:RSVPD {id: {rsvp_id}}]->(event)
ON CREATE SET rsvpRel.created = toint({mtime})
ON MATCH  SET rsvpRel.lastModified = toint({mtime})
SET rsvpRel.response = {response}

具体关系类型

MATCH (event:Event {id: {event_id}})
MATCH (member:Member {id: {member_id}})FOREACH(ignoreMe IN CASE WHEN {response} = "yes" THEN [1] ELSE [] END |MERGE (member)-[rsvpYes:RSVP_YES {id: {rsvp_id}}]->(event)ON CREATE SET rsvpYes.created = toint({mtime})ON MATCH  SET rsvpYes.lastModified = toint({mtime})MERGE (member)-[oldRSVP:RSVP_NO]->(event)DELETE oldRSVP
)FOREACH(ignoreMe IN CASE WHEN {response} = "no" THEN [1] ELSE [] END |MERGE (member)-[rsvpNo:RSVP_NO {id: {rsvp_id}}]->(event)ON CREATE SET rsvpNo.created = toint({mtime})ON MATCH  SET rsvpNo.lastModified = toint({mtime})MERGE (member)-[oldRSVP:RSVP_YES]->(event)DELETE oldRSVP
)

如您所见,使用特定的关系类型时,更新RSVP的代码更加复杂,部分原因是Cypher尚未对条件提供一流的支持。

总而言之,对于我们的metup.com模型,我们通过使用更具体的关系类型获得了速度上的提高,但是却以一些更复杂的读取查询和更为复杂的更新查询为代价。

根据模型中关系的基数,您的里程可能会有所不同,但是值得进行一些分析以比较所有选项。

翻译自: https://www.javacodegeeks.com/2015/12/neo4j-specific-relationship-vs-generic-relationship-property.html

Neo4j:特定关系与一般关系+属性相关推荐

  1. 关系模式的任何属性(关系模式的任何属性为什么不可再分)

    关系模式是什么呢? 关系是元组的集合,因此关系模式必须指出这个元组集合的结构,即它由哪些属性构成,这些属性来自哪些域,以及属性与域之间的映象关系 资产的属性与计量模式的关系是什么? 对资产的这一认识, ...

  2. neo4j 两个点创建关系_Neo4j:找到两个纬度/经度之间的中间点

    neo4j 两个点创建关系 昨天我写了一篇博客文章,展示了如何使用Cypher查找两个纬度/经度之间的中点,这是第一次尝试填补缺失位置时的效果,但是我意识到我可以做得更好. 正如我在上一篇文章中提到的 ...

  3. EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public?

    前言 不知我们是否思考过一个问题,在关系映射中对于导航属性的访问修饰符是否一定必须为public呢?如果从未想过这个问题,那么我们接下来来探讨这个问题. EF 6.x和EF Core 何种情况下必须配 ...

  4. mysql三国人物库_一文带你使用neo4j生成三国人物社交关系图

    简介 最近给孩子买了三国演义,可是三国人物关系太复杂,就想着把三国人物关系做成一张图,这样方便看,整好neo4j图数据库非常适合社交关系的处理,下面就一起来看看,如何使用neo4j生成三国人物社交关系 ...

  5. 数据库复习基本概念——关系、元组、属性、码、域、分量、形式化定义

    1)关系(Relation) 一个关系对应通常说的一张表 2)元组(Tuple) 表中的一行即为一个元组 3)属性(Attribute) 表中的一列即为一个属性,给每一个属性起一个名称,即属性名 4) ...

  6. 实体-关系图转换为关系模型

    1.逻辑设计概述   概念结构是独立于任何一种数据模型的,在实际应用中,一般所用的数据库环境已经给定(如SQL Server或Oracel或MySql),本文讨论从概念结构向逻辑结构的转换问题.    ...

  7. 关系型数据库(一)---关系数据模型与关系

    文章目录 前言 一.数据模型 1.什么是数据模型 2.数据模型的基本要素 (1)数据结构 (2)数据操作 (3)数据的约束条件 二.关系数据模型 1.关系数据模型的基本概念 (1)关系实例 (2)关系 ...

  8. mysql关系模式_关系数据模型是什么

    关系数据模型是一种数据模型,以关系或表格的形式对数据进行建模,是用来表示数据在关系数据库中的存储和处理方式,在关系数据库中会以关系(表)的形式来存储数据. 关系数据模型中有三大要素,分别为:关系数据结 ...

  9. (数据库系统概论|王珊)第二章关系数据库-第二节、第三节:关系操作和关系完整性

    文章目录 一:关系操作 (1)基本的关系操作 (2)关系数据语言的分类 二:关系完整性约束 (1)实体完整性 (2)参照完整性 A:参照关系 B:外码 C:参照完整性规则 (3)用户自定义完整性 一: ...

  10. 【数据库系统设计】关系数据库简介(关系模型、关系模式、关系完整性、关系代数)

    关系数据库 笔记目录 关系模型 关系数据结构 域 关系 关系模式 关系的三类完整性 实体元整性(Entity Integrity) 参照完整性 用户定义的完整性 关系代数 关系代数运算符 传统的集合运 ...

最新文章

  1. 20Composite(组合)模式
  2. python turtle循环图案-Python绘图Turtle库详解
  3. 97.PC 的串口是同步还是异步
  4. css搜索框变圆脸角,CSS浮动布局
  5. 【从零之三(更)】自定义类中调用讯飞语音包错误解决办法
  6. QT学习笔记(三):Qt软件打包发布(QT5.8 _msvc2013_64+Win10_64)
  7. centos linux怎么安装mysql_CentOS-Linux系统下安装MySQL
  8. php显示几个字符串,比较php中的两个字符串并显示字符差异
  9. 数据结构之二叉树_二叉排序树(严蔚敏C语言版)
  10. Delphi2010Excel导入数据库
  11. shell命令实现txt文件转换为csv文件
  12. Anaconda虚拟环境管理(命令行)
  13. GAMES104实录 | 游戏引擎导论(上)
  14. 如何在职场上获得良好的起点
  15. win10计算机怎么打开方式,Win10如何还原打开方式?还原打开方式的方法
  16. React的箭头函数详解
  17. vue如何在一个工程里判断h5还是pc,(利用在一个页面显示不同router-view内容原理,本文只使用于单页面项目,多页面项目请查看我另一篇博文)
  18. C51单片机实现呼吸灯
  19. Scratch课程设计(三)
  20. CPU 64位和32位

热门文章

  1. TypeError: Cannot set property 'msg' of undefined
  2. 为什么总是喜欢看我桌面呢?
  3. 每日top3热点搜索词统计案例
  4. mybatis的$和#详解分析
  5. docker 买了腾讯服务器后的学习
  6. android通讯录增删改查,android 通话记录的增删改查 .
  7. 收敛和发散思维如何被用作解决问题的手段
  8. 动态资源Servlet接口
  9. Spring_02_AOP初级总结
  10. java 和javafx_Java,JavaFX的流利设计风格文本字段和密码字段