读图数据库实战笔记04_路径与图变异

2023-10-31 07:45

本文主要是介绍读图数据库实战笔记04_路径与图变异,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. Groovy

1.1. Java编程语言的一个超集

1.2. Gremlin Console的一个特性是能和Groovy配合使用

1.2.1. Gremlin Console会自动地迭代结果

1.3. 从技术上说,Gremlin Console就是Groovy交互式解释器(read-eval-print loop,REPL)

1.3.1. 既可以作为一个独立的程序运行,也可以很容易地在其他程序中作为整体程序的一部分使用

2. 变异(mutation)

2.1. 简单地被理解为通过添加、修改或删除顶点、边和/或属性来改变图

2.2. 变异遍历或变异过程是在某种程度上改变图的内容或结构的操作

3. 添加顶点

3.1. INSERT INTO person (first_name) VALUES ('Dave');

3.2. 在图中添加顶点相当于在关系数据库中添加实体

3.3. 过程

3.3.1. 给定一个遍历源g

3.3.2. 添加一个新的顶点,类型是person

3.3.3. 在该顶点上添加一个属性,键是first_name,值是Dave

3.4. groovy

g.addV('person').property('first_name', 'Dave')
==>v[13]

3.4.1. 只需要为每一个addV()操作增加一个单一顶点

3.4.2. addV(label)

3.4.2.1. 在图中增加一个类型为label的顶点并返回这个新增顶点的引用

3.4.3. property(key, value)

3.4.3.1. 在顶点或边上增加一个属性
3.4.3.2. 该属性包含指定的key和value
3.4.3.3. 返回对进入该操作的顶点或边的引用

3.4.4. v[13]

3.4.4.1. 顶点的唯一的识别码
3.4.4.2. 这个ID值是根据数据库的当前状态内部生成的
3.4.4.2.1. 顶点的ID值应该被视为图数据库引擎的内部信息
3.4.4.2.2. 对数据库引擎等工具的内部信息,你应该保持足够的警惕
3.4.4.2.3. 为了应用程序的需要而在应用代码中使用它们则是极其危险的
3.4.4.3. Gremlin Server,在顶点上使用简单整数(32位),在边上使用长整数(64位)
3.4.4.4. 其他图数据库引擎可能会使用UUID或GUID
3.4.4.5. 虽然可以在代码中运用这些值,但最佳实践是不去使用它们

3.5. g.V().addV('person')

3.5.1. V()操作不仅代表图中的所有顶点,也会返回所有顶点

3.5.1.1. 下一个操作将在上一步操作输出的每个元素上执行

3.5.2. 图中的每一个现有顶点都会被添加一个person顶点

3.5.3. 在某些情况下,这可能是我们想要的结果

4. 添加边

4.1. 在关系数据库世界里,实体间的连接是通过外键隐式实现的

4.2. 在图的世界里,这些连接需要通过边来显式添加

4.3. 在添加边时,需要为它指定入顶点和出顶点

4.4. SELECT * FROM table1 WHERE id = (SELECT id1 FROM table2);

4.5. 过程

4.5.1. 给定一个遍历源g

4.5.2. 添加一条标签为friends的边

4.5.3. 分配边的出顶点是键为first_name、值为Ted的顶点

4.5.4. 分配边的入顶点是键为first_name、值为Hank的顶点

4.6. groovy

g.addE('friends').from(V().has('person', 'first_name', 'Ted')).to(V().has('person', 'first_name', 'Hank'))
==>e[15][4-friends->6]

4.6.1. addE(label)

4.6.1.1. 添加一条标签为label的边

4.6.2. from(vertex)

4.6.2.1. 指定边从哪个顶点开始的调节器

4.6.3. to(vertex)

4.6.3.1. 指定边在哪个顶点结束的调节器

4.6.4. 操作调节器不能单独使用

4.6.5. 调节器来源于TinkerPop,但提供开始顶点和结束顶点的细节则是通用需求

5. 删除顶点

5.1. DELETE FROM person WHERE person_id = 13;

5.2. 过程

5.2.1. 给定一个遍历源g

5.2.2. 找到一个ID为13的顶点

5.2.3. 删除这个顶点

5.3. g.V(13).drop()

5.3.1. V(id)

5.3.1.1. 返回id指定的顶点
5.3.1.2. 这个id是由Gremlin Server(其选择的数据库)分配和维护的内部ID

5.3.2. drop()

5.3.2.1. 删除任何经过它的顶点、边或属性
5.3.2.2. 没有任何返回结果
5.3.2.2.1. 发挥作用之后,它不会向客户端返回任何消息

6. 删除边

6.1. 方式1

6.1.1. 如果删除开始顶点或结束顶点,那么任何与该顶点关联的边也会被删除,这是图数据库版本的引用完整性体现

6.2. 方式2

6.2.1. 显式地删除它们,留下开始顶点和结束顶点

6.3. 过程

6.3.1. 给定一个遍历源g

6.3.2. 找到一条ID为15的边

6.3.3. 删除这条边

6.4. g.E(15).drop()

6.4.1. 在TinkerPop中,g.E()的默认实现需要一个类型为Long而不是int的参数,在Java中要留意这一点

6.4.2. 几乎和删除顶点的语句一模一样

6.4.2.1. 这种相似的语法也昭示了顶点和边在图数据库中同等重要

7. 修改图

7.1. UPDATE person SET first_name = 'Dave' WHERE first_name = 'Dav';

7.2. 过程

7.2.1. 给定一个遍历源g

7.2.2. 找到一个键为first_name、值为Dav的顶点

7.2.3. 修改该顶点的属性,将其值改为Dave

7.3. groovy

g.V().has('person', 'first_name', 'Dav').property('first_name', 'Dave')
==>v[18]

8. 脚本变异

8.1. groovy

g.V().drop().iterate()
dave = g.addV('person').property('first_name', 'Dave').next()
josh = g.addV('person').property('first_name', 'Josh').next()
ted = g.addV('person').property('first_name', 'Ted').next()
hank = g.addV('person').property('first_name', 'Hank').next()
g.addE('friends').from(dave).to(ted).next()
g.addE('friends').from(dave).to(josh).next()
g.addE('friends').from(dave).to(hank).next()
g.addE('friends').from(josh).to(hank).next()
g.addE('friends').from(ted).to(josh).next()

8.2. Gremlin代码的第一行是g.V().drop().iterate(),用来清除图中的所有数据

8.3. iterate()操作和next()操作类似,都会触发遍历

8.4. iterate()操作不会返回结果,而next()操作会返回遍历的结果

8.5. 由于drop()操作不返回值,因此这里使用iterate()操作比next()操作更合适

8.6. dave = g.addV('person').property('first_name', 'Dave').next()

8.6.1. 要在添加边之前把相应的顶点创建好

8.6.2. 过程

8.6.2.1. 给定一个遍历源g
8.6.2.2. 添加一个含有标签person的新顶点
8.6.2.3. 为这个顶点添加一个键为first_name、值为Dave的属性
8.6.2.4. 执行这些操作,返回迭代中的第一个(下一个)项作为结果

8.6.3. 声明保存遍历结果的变量dave

8.6.3.1. 变量是图世界中另一种差别的源头
8.6.3.1.1. Cypher,不支持这种跨请求的查询
8.6.3.1.2. 甚至在支持TinkerPop的图数据库间的支持程度都不一样
8.6.3.1.3. 不管是Azure的CosmosDB还是Amazon Nepture,都没有这个功能
8.6.3.1.4. JanusGraph和DataStax Enterprise Graph则完全支持
8.6.3.1.5. 如果查询语言和数据库支持变量的话,我们推荐使用它们
8.6.3.1.6. 变量可以极大地简化某些操作
8.6.3.1.6.1. 把添加顶点和边的操作串联在一起
8.6.3.2. 当要把结果赋值给一个变量时,则不得不包含终端操作
8.6.3.3. 否则,整个迭代集会被分配到变量中,而不只是迭代集里的那些结果
8.6.3.4. 这不是一个幂等的操作

8.6.4. next()

8.6.4.1. 一个终端操作,它从上一个操作获得迭代遍历源,迭代一次,然后返回迭代中的第一个或下一个项
8.6.4.2. 类似于iterate()的终端操作
8.6.4.3. 可以把它想成一个强制遍历循环的操作

8.7. g.addE('friends').from(dave).to(ted)

8.7.1. 给定一个遍历源g

8.7.2. 增加一条标签为friends的边

8.7.3. 出顶点指向dave变量

8.7.4. 入顶点指向ted变量

9. 链式变异

9.1. 在图数据库中,变异可以链接在一起,以同时执行多个变更

9.2. groovy

g.addE('friends').from(dave).to(josh).addE('friends').from(dave).to(hank).addE('friends').from(josh).to(hank).addE('friends').from(ted).to(josh).iterate()

9.3. 要在一个语句中包含复杂的操作,链接操作是Gremlin中的基本策略

9.3.1. 每一个操作从上一个操作的输出获取数据,并在处理后将该数据交给下一个操作

9.3.2. 对于熟悉函数式编程的朋友来说,这一切都似曾相识

9.4. 图遍历中的变异操作允许把多个变异操作链接成一个操作,而SQL做不到这一点

10. 路径(path)

10.1. 在遍历中从开始顶点访问到结束顶点之间的所有顶点和边的列表

10.2. 不仅告诉我们两个顶点是连接的,而且展示了它们之间的所有中间元素

10.3. 路径描述了从开始顶点到结束顶点的一系列遍历操作

10.4. 路径代表一系列连接两个元素的顶点和边

10.5. 意味着我们不仅能发现两个顶点是相互连接的,而且能确定如何从起点到达终点

10.6. groovy

g.V().has('person', 'first_name', 'Ted').until(has('person', 'first_name', 'Denise')).repeat(both('friends')).path()

10.6.1. path()

10.6.1.1. 当遍历执行时,返回指定遍历器访问顶点(某些时候还有边)的历史
10.6.1.2. 在Gremlin中使用path()操作会增加服务器的资源消耗,因为每个遍历器都需要维护自己访问的所有历史记录
10.6.1.3. 只在需要所有路径数据时使用path()

10.7. groovy

Script evaluation exceeded the configured 'scriptEvaluationTimeout' thresholdof 30000 ms or evaluation was otherwise cancelled directly for request[g.V().has('person', 'first_name', 'Ted').until(has('person', 'first_name', 'Denise')).repeat(both('friends')).path()]
Type ':help' or ':h' for help.

10.7.1. 遍历超时了

10.7.2. 图中生成了一个环

10.7.2.1. 环是图论中的一个概念,指的是图中顶点和边的路径包含一个或多个能到达自己的顶点
10.7.2.2. 环指的是含有重复顶点的路径,通常会在图遍历过程中引起长时间运行的循环与寻路查询

10.7.3. :clear命令清除缓存并重新启动遍历

11. 简单路径

11.1. 不会在任何一个顶点上重复的路径

11.2. 在简单路径中只会得到非环的结果

11.2.1. 简单路径就是图中不含重复顶点的路径

11.3. 每个遍历器会维护它访问的所有项的历史

11.3.1. 当碰到一个曾经访问过的项时,它就知道这个元素在环中,并把它剔除

11.3.2. 只有那些不含环的遍历器会继续完成遍历工作

11.4. groovy

g.V().has('person', 'first_name', 'Ted').until(has('person', 'first_name', 'Denise')).repeat(both('friends').simplePath()).path()
==>path[v[4], v[0], v[15], v[19]]
==>path[v[4], v[0], v[13], v[19]]
==>path[v[4], v[2], v[0], v[15], v[19]]
==>path[v[4], v[2], v[0], v[13], v[19]]
==>path[v[4], v[0], v[15], v[17], v[19]]
==>path[v[4], v[0], v[15], v[13], v[19]]
==>path[v[4], v[0], v[13], v[15], v[19]]
==>path[v[4], v[2], v[6], v[0], v[15], v[19]]
==>path[v[4], v[2], v[6], v[0], v[13], v[19]]
==>path[v[4], v[2], v[0], v[15], v[17], v[19]]
==>path[v[4], v[2], v[0], v[15], v[13], v[19]]
==>path[v[4], v[2], v[0], v[13], v[15], v[19]]
==>path[v[4], v[0], v[13], v[15], v[17], v[19]]
==>path[v[4], v[2], v[6], v[0], v[15], v[17], v[19]]
==>path[v[4], v[2], v[6], v[0], v[15], v[13], v[19]]
==>path[v[4], v[2], v[6], v[0], v[13], v[15], v[19]]
==>path[v[4], v[2], v[0], v[13], v[15], v[17], v[19]]
==>path[v[4], v[2], v[6], v[0], v[13], v[15], v[17], v[19]]

11.4.1. simplePath()

11.4.1.1. 筛选掉遍历中被重复访问的顶点
11.4.1.2. 如果把simplePath()放在遍历末尾,它就在循环逻辑之外了,遍历器会被困在环里,无法离开
11.4.1.3. 就像在Java里创建一个for循环,但把计数器变量放在for循环之外

12. 遍历和筛选边

12.1. 从顶点走到边,再从边走到顶点。必须显式遍历到边,并显式从边离开

12.2. 边可以直接被遍历和筛选,不需要遍历到相邻的顶点

12.3. InE(label)

12.3.1. 从当前顶点遍历到相邻的入边

12.4. outE(label)

12.4.1. 从当前顶点遍历到相邻的出边

12.5. bothE(label)

12.5.1. 从当前顶点遍历到相邻边,不考虑方向

12.6. 如果指定了标签,只遍历到符合筛选条件的边

12.7. 每个E操作都从一个顶点开始,遍历到一条边,然后停留在这条边上

12.7.1. 这些操作都结束于边,而不是相邻的顶点

12.8. inV()

12.8.1. 从当前边遍历到入顶点

12.8.2. 通常和outE()操作搭配使用

12.8.2.1. 组合来完成到相邻顶点的遍历

12.9. outV()

12.9.1. 从当前边遍历到出顶点

12.9.2. 通常和inE()操作搭配使用

12.9.2.1. 组合来完成到相邻顶点的遍历

12.10. otherV()

12.10.1. 遍历到不是出顶点的那个顶点(如另一个顶点)

12.10.2. 通常和bothE()操作搭配使用

12.10.2.1. 轻松地带到“另一个顶点”上,不是遍历出发的那个顶点

12.11. bothV()

12.11.1. 从当前边遍历到两个相邻的顶点

12.11.2. 极少用到

12.12. groovy

g.V().has('person','first_name','Dave').bothE('works_with').otherV().values('first_name')
==>Ted
==>Josh
==>Hank
==>Kelly
==>Denise

12.13. groovy

g.V().has('person', 'first_name','Dave').both('works_with').values('first_name')
==>Ted
==>Josh
==>Hank
==>Kelly
==>Denise

12.14. groovy

g.V().has('person', 'first_name', 'Ted').until(has('person', 'first_name', 'Denise')).repeat(bothE('works_with').otherV().simplePath()).path()
==>path[v[4], e[29][0-works_with->4], v[0], e[33][0-works_with->19], v[19]]
==>path[v[4], e[29][0-works_with->4], v[0], e[32][0-works_with->13], v[13],e[34][19-works_with->13], v[19]]
==>path[v[4], e[30][2-works_with->4], v[2], e[28][0-works_with->2], v[0],e[33][0-works_with->19], v[19]]
==>path[v[4], e[30][2-works_with->4], v[2], e[28][0-works_with->2], v[0],e[[32][0-works_with->13], v[13], e[34][19-works_with->13], v[19]]

12.14.1. bothE().otherV()遍历模式来显式地遍历到边上

12.14.2. 在路径结果中包括边

12.14.3. 航空交通路线

12.14.3.1. 顶点代表机场,边代表机场间的航班

13. 通过属性筛选边

13.1. 基于时间的筛选

13.2. 基于权重的筛选

13.3. groovy

g.V().has('person','first_name','Dave').bothE('works_with').has('end_year',lte(2018)).otherV().values('first_name')
==>Josh
==>Ted
==>Hank

13.3.1. 可以基于边的属性进行筛选

13.3.2. 使用一些断言操作,如代表“小于或等于”的lte()

13.3.3. 对于比单值匹配更复杂的操作,断言操作是非常好用的管理工具

14. 边的计数

14.1. g.V().bothE().count()

14.2. g.V().both().count()

14.2.1. 通过both()操作来计数通常代价更高昂

15. 反规范化(denormalization)

15.1. 把经常访问的顶点属性复制到相邻的边上

15.2. 它对于某些以读为主的活动类型特别有帮助

15.3. 会带来维护同一个属性值的两份副本的开销

15.4. 维护数据的多个副本就是反规范化,不管使用关系数据库还是图数据库,反规范化都会带来这种额外的开销

这篇关于读图数据库实战笔记04_路径与图变异的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/313852

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

hdu2544(单源最短路径)

模板题: //题意:求1到n的最短路径,模板题#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#i

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

poj 1734 (floyd求最小环并打印路径)

题意: 求图中的一个最小环,并打印路径。 解析: ans 保存最小环长度。 一直wa,最后终于找到原因,inf开太大爆掉了。。。 虽然0x3f3f3f3f用memset好用,但是还是有局限性。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#incl

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10