读图数据库实战笔记08遍历与子图

news/2024/12/20 7:22:05/文章来源:https://www.cnblogs.com/lying7/p/18618133

1. 使用熟路构建遍历

1.1. 为了避免把开发遍历和构建应用程序混淆

  • 1.1.1. 把遍历的编写和测试与应用程序的开发拆分成了两个独立的操作

  • 1.1.2. 在Java代码之外独立开发遍历,然后把它们加入应用程序中

  • 1.1.3. 现实情况是,大多数开发人员会同时完成两者,不管使用的是哪种数据库引擎

1.2. 开发熟路遍历要识别模式的有关部分,寻找遍历的起点和终点,识别从起点到终点遍历所需的一系列顶点和边,最后循序渐进、迭代式地增加操作来组成遍历,并通过测试数据验证每一步的结果

1.3. 好的遍历起点可以最小化开始顶点,最理想的情况是只有一个顶点

2. 开发遍历的准备工作

2.1. 用例的需求

  • 2.1.1. 为用例开发遍历要从识别回答业务疑问所需的顶点和边开始

2.2. 图数据模型

2.3. 在把业务疑问转换为技术需求与实现时,代词很容易被忽略,这会隐藏额外的、更细微的需求

2.4. 识别所需的元素

  • 2.4.1. 检视每一个需求,并将其拆分成回答该疑问所需的组件

  • 2.4.2. 识别所需的顶点标签

  • 2.4.2.1. 最好的起点就是寻找需求中的名词

  • 2.4.2.2. 在数据模型中寻找这些名词对应的顶点标签

  • 2.4.2.3. 定位起点是为了寻找和疑问有关的部分,从而把遍历收缩到数量最少的开始顶点

  • 2.4.3. 识别所需的边标签

  • 2.4.3.1. 一旦识别了需求中的动词,就可以查找数据模型中相应的边名了,就像找名词那样

2.5. 选择起点

  • 2.5.1. 选择我们认为最具挑战性的问题,并从它入手

  • 2.5.1.1. 这个方式适合有大量未知因素或大量项目风险的情况

>  2.5.1.1.1. 向开发生态系统引入新技术或新流程
  • 2.5.1.2. 这个方式能让我们快速失败,也是需要快速决策时的正确选择
>  2.5.1.2.1. 需要决定是否继续>  2.5.1.2.2. 确定某项技术是否是解决某个问题的正确选择
  • 2.5.2. 从最直接或最不复杂的疑问开始,并以此作为之后工作的基石

  • 2.5.2.1. 这条道路倡导代码的渐进式开发,也很好地避免了囫囵吞枣

  • 2.5.2.2. 该方式的意义在于快速获取成功,或者在处理更复杂的问题之前,从更小、更简单的问题中获得成就感

  • 2.5.2.3. 从最不复杂的疑问开始,我们就能在解决更复杂的问题之前从更小、更简单的问题那里获得成功

2.6. 准备测试数据

  • 2.6.1. 加载测试数据

  • 2.6.2. 在对数据有错误假设的其他情景中,增加样本数据可能是最佳方式

  • 2.6.3. 在排查此类错误的时候,你手上还有其他资源

  • 2.6.3.1. 和同事讨论问题能帮助你获得解决方案

  • 2.6.3.2. 另一种可行的方式是尝试以更受控的方式复制相关条件,也许是使用更小的数据集

  • 2.6.4. 采用一步接一步的系统性方式构建遍历可以使遇到错误时的排查变得更容易

3. 编写第一个遍历

3.1. 设计遍历

  • 3.1.1. 布丁好不好,吃过才知道

3.2. 开发遍历代码

  • 3.2.1. 在Gremlin Server里,日期是以世界协调时(Coordinated Universal Time,UTC)的格式保存的

  • 3.2.1.1. 为了显示,Gremlin Console会自动将其转换成本地时区的日期

  • 3.2.2. 通过ID扩展遍历

  • 3.2.3. 开发熟路遍历所需的功夫确实比开发社交网络需要的多,但最艰巨的任务已经完成了

  • 3.2.4. mean():聚合一组值来计算平均值,常用与group().by().by()操作搭配使用

  • 3.2.5. has()操作是首要的筛选操作,也是基于属性实现筛选逻辑的首选

  • 3.2.6. where()操作通常用于其他情况的筛选——基于比简单属性匹配更复杂的逻辑组合的筛选

  • 3.2.7. identity():获取进入该操作的元素并原封不动地返回

  • 3.2.8. optional(traversal):尝试遍历,如果返回结果,则发出结果;否则,发出传入元素(与identity()操作一样)​

  • 3.2.9. lues标识和values()操作是不一样的

  • 3.2.9.1. values标识指向键-值对的值部分

  • 3.2.9.2. values()指定从元素中返回的属性

3.3. 对遍历进行分组和排序会创建键-值对形式的结果

  • 3.3.1. 对键-值对的进一步处理会采用select()操作的一个特殊重载,分别对键-值对中键的部分和值的部分进行处理

3.4. 在遍历过程中越早进行筛选,意味着在图中移动的遍历器越少,因此要做的总体工作也越少

4. 分页和图数据库

4.1. offset(偏移值)​

  • 4.1.1. 要跳过的记录数量

  • 4.1.2. 在数据集的起点,offset =0

  • 4.1.3. 偏移值是分页大小的倍数

  • 4.1.3.1. 如果分页大小是10,偏移值则可能是0、10、20、30等

4.2. limit(限制值)

  • 4.2.1. 分页大小或要返回项的最大数量

  • 4.2.2. 限制值是要返回项的最大数量,是因为结果集并不总是分页大小

  • 4.2.2.1. 最后一页所含的项比分页大小要少

4.3. range(startNumber, endNumber)

  • 4.3.1. 穿过各个对象,从startNumber开始(包含该索引位置的对象)​,直到endNumber(不包含该索引位置的对象)​

  • 4.3.2. startNumber是包含在返回结果中的

  • 4.3.2.1. startNumber和offset一样

  • 4.3.3. endNumber被排除在返回结果以外

  • 4.3.3.1. endNumber则不是关系数据库中使用的limit,而是startNumber +limit

  • 4.3.3.2. 分页功能要以offset和limit作为常规输入,计算endNumber

  • 4.3.4. 调用range()前为输入排序的重要性

  • 4.3.4.1. 数据库引擎基于其内部逻辑决定结果的顺序

  • 4.3.4.2. 要给用户提供一致的体验,就必须在调用range()操作前进行排序

  • 4.3.5. 排序是昂贵的操作

  • 4.3.5.1. 对结果进行排序在任何数据库中都是昂贵的操作,特别是对于大型数据集来说

  • 4.3.5.2. 键-值对很容易使用,前提是能以它们的值来排序

4.4. 在关系数据库中处理分页的通用模式和在图数据库里是一样的

  • 4.4.1. 获取遍历的结果

  • 4.4.2. 找到offset索引指定的记录

  • 4.4.3. 返回结果的limit数

  • 4.4.4. 根据新的偏移值offset + limit重复以上过程

4.5. 方式1是一直运行遍历,递增offset,直到它返回空的结果集为止

  • 4.5.1. 适应的场景是:预期的结果数量很大,而且不需要知道总数;或者想避免提前为所有结果计数的开销

4.6. 方式2是预设可能的结果总数,并把它作为offset + limit值的上限

  • 4.6.1. 对于应用程序需要知道显示结果总数的场景特别有用

4.7. 在图遍历中对结果进行分页需要以排序后的结果集作为输入,并运用限制值和偏移值指定期望的结果子集

5. 五个通用操作

5.1. general step​

5.2. map、flatMap、filter、branch、sideEffect

  • 5.2.1. 这五个通用操作是编程的核心概念

5.3. 所有的Gremlin操作,除了调整或配置其他操作的操作之外,本质上都是这五个通用操作之一的优化版本

6. 子图

6.1. 个性化是基于数据中的连接关系筛选数据以提供最相关内容的过程

  • 6.1.1. 只专注于数据的一个子集​,而忽略另一个子集​

  • 6.1.2. 子图天然适合个性化问题

6.2. 因为只就图中明确定义的部分数据提出疑问,所以我们只想处理这个数据子集

  • 6.2.1. 做到这一点的最有效方法是从全局图中提取该数据子集

  • 6.2.2. 这是一个常见的操作,该数据子集称为子图

  • 6.2.3. 就是顶点和边的子集,通常根据某种规则或对业务领域的理解而紧密相连

6.3. 子图是图数据的子集,包含用来表示图的顶点和边

  • 6.3.1. 子图本身就是图

  • 6.3.2. 意味着我们可以在子图上运行遍历,但是因为子图被限制在一小部分顶点和边上,所以只需要更少的内存和计算能力

7. 使用子图

7.1. 并不是所有的图数据库产品都有显式的子图支持

7.2. 子图也是图,只是其中的所有顶点和边都是一个更大的图的子集

  • 7.2.1. 子图本身就是一张图的事实是子图如此有用的原因之一:它们的工作原理与更大的图一样,但内存占用更少

  • 7.2.2. 子图是以图的形式返回的,所以一旦为子图创建了图遍历源,就可以遍历这些子图并执行你学到的所有操作

7.3. 提取子图

  • 7.3.1. 按顶点归纳子图是通过一组顶点及其之间的边来定义的

  • 7.3.1.1. 按顶点归纳子图包括顶点之间的所有边

  • 7.3.2. 按边归纳子图是通过一组边及其相邻顶点来定义的

  • 7.3.2.1. 按边归纳子图只包括那些被定义的边

  • 7.3.2.2. 使用边来定义范围似乎有违直觉

>  7.3.2.2.1. 从历史上看,我们在考虑数据时总是抱着一种实体第一(甚至是实体唯一)的思维方式
  • 7.3.2.3. 图的实体关系允许我们使用边作为“一等公民”来定义子图的限度

  • 7.3.2.4. Gremlin Server的TinkerPop实现支持按边归纳子图,因此按边归纳子图将是个性化用例的重点

  • 7.3.3. 两种方法的结果并非总是不同

  • 7.3.3.1. 子图的组成取决于你使用的方法以及在选择过程中使用的规则

  • 7.3.4. subgraph(sideEffectKey):在一组较大的图数据中定义一个按边归纳子图

  • 7.3.4.1. sideEffectKey是对副作用完整结果的引用

  • 7.3.4.2. 副作用是我们改变状态的方式

  • 7.3.4.3. subgraph()操作的主要作用是返回作为其输入的边

  • 7.3.4.4. 该操作的副作用部分将这些相同的边及其相邻顶点添加到了由标签标识的内部集合中

  • 7.3.4.5. TinkerPop的subgraph()操作有一个关键的限制:Gremlin语言变体(GLV)不支持它

>  7.3.4.5.1. GLV没有包括局部图的概念,这意味着我们不能返回子图,然后将其用于进一步的遍历>  7.3.4.5.2. GLV不支持子图,因此必须使用脚本提交方法来参数化并拼接字符串以编写遍历
  • 7.3.4.6. subgraph变量只存在于会话中的服务器上

  • 7.3.5. cap(sideEffectKey):向上迭代遍历到自身,并发出sideEffectKey引用的副作用结果

7.4. 遍历子图

  • 7.4.1. Graph是一个数据存储

  • 7.4.1.1. 只是存放数据的地方,除了最简单的查找操作以外,没有访问数据的其他能力

  • 7.4.2. GraphTraversalSource是编写所有遍历的基础(遍历中的g)​

  • 7.4.2.1. 没有GraphTraversalSource的图对象就相当于没有任何类型文件管理器的文件系统及其文件

  • 7.4.2.2. 没有任何类型的工具来导航文件系统、读取文件及其属性或者移动文件

>  7.4.2.2.1. 在使用子图之前,需要获得遍历源

7.5. 将子图用于串行隔离

  • 7.5.1. 可以将其视为使用可序列化隔离模式与图数据交互的方式

  • 7.5.2. 子图是在图数据库中建立可序列化隔离的一种无奈方式

  • 7.5.3. 子图是没有磁盘缓存功能的内存结构,因此创建整个原始图的子图可能会造成内存压力,甚至会引发内存不足错误

  • 7.5.4. 根据可串行隔离的定义,子图中发生的任何变化都不会反映在原始图中,反之亦然

  • 7.5.4.1. 要依靠应用程序开发人员来协调两者之间的变化

  • 7.5.5. 子图可以被复用甚至修改,但所做的任何更改都是与原始图隔离的

  • 7.5.5.1. 意味着任何更改都不会传回原始图数据

7.6. 遍历末尾还包含了文本; null

  • 7.6.1. 分号(;)用于结束第一个语句,即子图变量的赋值

  • 7.6.2. null用于将整个操作返回给客户端

8. 反转遍历方向

8.1. 在大多数关系数据库建模中,特别是使用第三范式时,外键被设计为只在一个方向上使用

  • 8.1.1. 如果要支持相反方向的连接,通常代价很高

8.2. 对于大多数图数据库来说,支持相反方向的连接不会产生额外的性能成本

8.3. 在关系数据库世界中,简单地改变关系的方向几乎是闻所未闻的,但对于图数据库来说,这几乎是一个微不足道的变化

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

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

相关文章

使用css实现圆形的头像的效果(注:要考虑正方形、长方形情况)

在前端开发中,我们经常需要将用户的头像显示为圆形。这可以通过CSS的 border-radius 属性来实现,该属性允许你设置元素的圆角。当 border-radius 设置为 50% 时,无论图片是正方形还是长方形,都会得到一个圆形的效果。但需要注意,长方形图片被裁剪为圆形时,会显示为椭圆形…

任意尺度图像超分辨率的基准技术分析

任意尺度图像超分辨率的基准技术分析 在计算机视觉领域,超分辨率(SR)一直是一个突出的研究领域。它的目的是从低分辨率(LR)图像重建高分辨率(HR)图像。最近,主要基于学习图像的连续表示的任意尺度图像SR取得了重大进展。 这些方法通常需要在特定范围内(即1.0-4.0)使用…

用于端到端场景图生成的密集关系变换器

用于端到端场景图生成的密集关系变换器 场景图生成旨在捕捉图像中对象之间的详细空间和语义关系,由于标签不完整、长尾关系类别和关系语义重叠,这具有挑战性。现有的基于Transformer的方法要么对对象和谓词采用不同的查询,要么对关系三元组采用整体查询,因此学习低频关系的…

新书推荐《AI芯片开发核心技术详解》、《智能汽车传感器:原理设计应用》

由清华大学出版社资深编辑赵佳霓老师策划编辑的新书《AI芯片开发核心技术详解》已经出版,京东、淘宝天猫、当当等网上,相应陆陆续续可以购买。该书强力解析AI芯片的核心技术开发,内容翔实、知识点新颖、实践性很强、图文并茂。 由清华大学出版社资深编辑赵佳霓老师…

vue3/Nuxt中使用Toast

前言 实在是懒得手写一个toast,于是找了一下。 过程 https://github.com/Maronato/vue-toastification/tree/next vue-toastification这个库很有名,默认是vue2的,如果需要使用vue3,需要在安装时,指定next的tag,比如 pnpm i vue-toastification@next但是这个库的最新版也已…

什么是状态管理,有哪些实现?

概念 “状态管理”是指在应用程序中有效地组织、更新和共享数据的方式。比起数据库和本地之类的持久层,有时我们需要存储一些应用运行过程中的临时数据,其中大部分可能都不会存入数据库。因此,状态这个词还是挺贴切的。比较熟悉的是vue中Pinia提供的状态管理,他是全局可访问…

[计算机网络/Linux] 基于CENTOS7自建DNS服务

序最初的诉求:自建DNS,篡改公开网站的url为自建web服务的url。在使用浏览器进行网上冲浪的时候,我们只需要输入网址即可访问,但是在网络中,网址并不是一个有效的东西,真正起作用的是网址所对应的IP地址,但是IP地址是一堆没有规律的数字,难以记忆、使用,所以就有了DNS服…

[计算机网络] 基于CENTOS7自建DNS服务

序最初的诉求:自建DNS,篡改公开网站的url为自建web服务的url。在使用浏览器进行网上冲浪的时候,我们只需要输入网址即可访问,但是在网络中,网址并不是一个有效的东西,真正起作用的是网址所对应的IP地址,但是IP地址是一堆没有规律的数字,难以记忆、使用,所以就有了DNS服…

systemd[1]: home.mount: Directory /home to mount over is not empty, mounting anyway.

日志显示这些内容说明可能是 fstab 服务自动挂载之前 /home 不为空systemd[1]: home.mount: Directory /home to mount over is not empty, mounting anyway. ░░ Subject: 挂载点不为空 ░░ Defined-By: systemd ░░ Support: http://www.ubuntu.com/support ░░ ░░ 目…

Linux服务器上部署Redis流程

前言 Redis版本7.0.4 服务器版本:Linux CentOS 8.0 64位 1.下载Redis 进入官网找到下载地址 https://redis.io/download 进入到Xshell控制台(默认当前是root根目录),输入wget 将上面复制的下载链接粘贴上,如下命令: wget http://download.redis.io/releases/redis-7.0.4.tar…

[Tools] Buzz – 免费开源的AI语音转文字工具

Buzz 介绍 https://github.com/chidiwilliams/buzz Buzz是一款基于OpenAI Whisper模型构建的离线语音转文字工具,适用于Windows、macOS和Linux系统。Buzz能将麦克风输入或音频、视频文件实时转换为文字,支持多种格式导入导出,如TXT、SRT和VTT。Buzz的转换速度快,准确率高,…

Skipping题解(贪心,队列,迪杰斯特拉,思维)

原题链接 https://codeforces.com/problemset/problem/2023/B 大致题意 类似一个游戏游戏规则如下:从1开始,可以选择吃掉ai,之后只能选择比当前下标小的(明显,如果开始就选择吃掉a1,那么游戏就结束了)。 当然还可以选择不吃ai,那么可以跳到[1,b[i]](b[i]与i的大小关系…