读图数据库实战笔记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. 维护数据的多个副本就是反规范化,不管使用关系数据库还是图数据库,反规范化都会带来这种额外的开销

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/175131.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【广州华锐互动】城市水处理VR仿真实训平台

随着科技的不断发展,虚拟现实(VR)技术已经逐渐渗透到各个领域,为我们带来了前所未有的沉浸式体验。在教育领域,VR技术的应用也日益广泛,为传统的教学模式带来了革命性的变革。本文将以城市水处理VR仿真实训…

[架构之路-246/创业之路-77]:目标系统 - 纵向分层 - 企业信息化的呈现形态:常见企业信息化软件系统 - 客户关系管理系统CRM

目录 前言: 一、企业信息化的结果:常见企业信息化软件 1.1 客户关系管理系统CRM 1.1.1 什么是客户关系管理系统 1.1.2 CRM总体架构 1.1.3 什么类型的企业需要CRM 1.1.4 创业公司在什么阶段需要CRM 1.1.5 研发型创业公司什么时候需要CRM 1.1.6 C…

3D RPG Course | Core 学习日记一:初识URP

前言 最近开始学习Unity中文课堂M_Studio(麦大)的3D RPG Course,学习一下3D RPG游戏核心功能的实现,第一课我们学习到的是地图场景的编辑,其中涉及到了URP渲染。 我们首先进入Unity资源商店把地图素材和人物素材导入好…

stable diffusion简介和原理

Stable Diffusion中文的意思是稳定扩散,本质上是基于AI的图像扩散生成模型。 Stable Diffusion是一个引人注目的深度学习模型,它使用潜在扩散过程来生成图像,允许模型在生成图像时考虑到文本的描述。这个模型的出现引起了广泛的关注和讨论&am…

leetcode-二叉树

B树和B树的区别 B树,也即balance树,是一棵多路自平衡的搜索树。它类似普通的平衡二叉树,不同的一点是B树允许每个节点有更多的子节点。 B树内节点不存储数据,所有关键字都存储在叶子节点上。B树: B树: 二叉…

mac安装并使用wireshark

mac安装并使用wireshark 1 介绍 我们在日常开发过程中,遇到了棘手的问题时,免不了查看具体网络请求情况,这个时候就需要用到抓包工具。比较著名的抓包工具就属:wireshark、fildder。我这里主要介绍wireshark。 2 安装 以mac安装为…

前端开发必备技能!用简单CSS代码绘制三角形,提升用户体验

🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 ⭐ 专栏简介 📘 文章引言 一、前…

Docker 容器服务的注册、发现及Docker安全

目录 Docker容器服务的注册和发现 1、什么是服务注册与发现? 2、什么是consul consul的部署 1、环境准备 2、部署consul服务器 1)建立 Consul 服务 2)设置代理,在后台启动 consul 服务端 3)查看集群信息 4&a…

图像视觉特效处理工具:Boris FX Optics 2024.0.1

BorisFX光效插件Optics首发2024版:3大新功能详解 2023年9月15日,全球领先的视觉后期软件开发公司BorisFX推出了旗下知名软件Boris FX Optics的全新2024版本,这款备受后期处理爱好者喜爱的Photoshop插件和独立程序再次升级,为您的…

Docker Consul概述及构建

Docker Consul概述及构建 一、Consul概述1.1、什么是Consul1.2、consul 容器服务更新与发现1.3、服务注册与发现的含义1.4、consul-template概述1.5、registrator的作用 二、consul部署2.1、环境配置2.2、在主节点上部署consul2.3 、配置容器服务自动加入nginx集群2.3.1、安装G…

Redis测试新手入门教程

在测试过程中,我们或多或少会接触到Redis,今天就把在小破站看到的三丰老师课程,把笔记整理了下,用来备忘,也希望能给大家带来亿点点收获。 主要分为两个部分: 一、缓存技术在后端架构中是如何应用的&#…

K8s集群

统一时间:ntpdate(都做) ntpdate -b ntp1.aliyun.com */1 * * * * /usr/sbin/ntpdate -b ntp1.aliyun.com systemctl status docker vi /etc/docker/daemon.json systemctl restart docker m: vim kubernetes.sh cat >> /etc/yum.repos.d/kubernetes.repo…

50元买来的iPhone手机刷机经验

前段时间,家里的iPad被家人误操作,导致iPad变成不可使用状态。自己折腾了半天,没有找到解决办法。没有办法,只好拿到手机维修店去修理,很快就修理好了.其实也很简单--就是对iPad进行了刷机操作。当然我也看到了刷机的方法。今天&a…

优化改进YOLOv5算法:加入SPD-Conv模块,让小目标无处遁形——(超详细)

1 SPD-Conv模块 论文:https://arxiv.org/pdf/2208.03641v1.pdf 摘要:卷积神经网络(CNNs)在计算即使觉任务中如图像分类和目标检测等取得了显著的成功。然而,当图像分辨率较低或物体较小时,它们的性能会灾难性下降。这是由于现有CNN常见的设计体系结构中有缺陷,即使用卷积…

MSQL系列(十) Mysql实战-Join驱动表和被驱动表如何区分

Mysql实战-Join驱动表和被驱动表如何区分 前面我们讲解了Mysql的查询连接Join的算法原理, 我发现大家都知道小表驱动大表,要让小表作为驱动表, 现在有2个问题 查询多表, 到底哪个是驱动表?哪个是被驱动表, 如何区分?索引如何优化,到底是加在驱动表上,还是被驱动表上? &…

初学编程入门基础教学视频,中文编程开发语言工具箱之豪华编辑构件,免费版中文编程软件下载

初学编程入门基础教学视频,中文编程开发语言工具箱之豪华编辑构件,免费版中文编程软件下载 构件的其中一个属性、方法,查找内容,替换内容。 构件工具箱非常丰富,其中该构件在 文本件构件板菜单下。 编程系统化课程总目…

C++类模板再学习

之前已经学习了C类模板;类模板的写法和一般类的写法有很大的差别;不容易熟悉;下面再做一遍; 做一个椭圆类,成员有长轴长度和短轴长度; // ellipse.h: interface for the ellipse class. // //#if !define…

李宏毅老师浅谈机器学习

李宏毅老师浅谈机器学习 引例 - 宝可梦/数码宝贝 分类器如何定义损失函数?- 经验这里定义一个直观的loss函数根据全体数据,得到最好的模型参数(理想)如何衡量现实损失和理想损失接近程度?如何得到跟含所有样本数据集很像的取样数据…

MFC实现堆栈窗口:多个子界面可任意切换

1、效果 在Qt中可使用QStackedWidget控件直接拖动布置即可实现,但在MFC中并未提供类似的控件,因此需要自己简单实现。 2、实现原理 实现原理比较简单,父级对话框在显示的区域部分,通过切换子对话框即可实现。子对话框去掉边框后…

idea使用MyBatisX插件

1.MyBatisX功能 (1).实现mapper和xml的跳转 (2).自动生成java文件,比如mapper、service、dao、pojo 2.安装MyBatisX插件 install后然后重启idea即可 3.使用MyBatieX实现mapper和xml跳转 (1).点击mapper中的红色图标即可跳转到对应的xml方…