为什么数据库查询语言很重要

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

为您的应用程序或开发堆栈寻找最佳数据库不仅仅关乎功能、可扩展性和性能。尽管所有这些都是必不可少的,但图形数据库的另一个元素被太多架构师忽视了:数据库查询语言。

大多数关系数据库 (rdbms) 使用 sql( 结构化查询语言 )的变体,使 sql 成为大多数数据专业人员 事实上的 数据库查询语言。但随着 比关系数据库更高效的图形数据库 的出现,是时候相应地转向更强大的查询语言了。

在这个“面向初学者的图形数据库”博客系列中,我将带您了解图形技术的基础知识,假设您在该领域的背景很少(或没有)。在过去的几周里,我们已经解决了 为什么图是未来 为什么数据关系很重要 数据建模的基础知识 以及 如何避免最常见(和致命)的数据建模错误

本周,我们将讨论为什么数据库查询语言很重要——即使您不是开发人员。

为什么我们需要查询语言

到目前为止,在我们的初学者系列中,我们所有的 数据库模型 都采用如下图所示的图表形式。



像这样的 图表 非常适合描述任何技术环境之外的图形数据库。然而,当谈到实际使用数据库时,每个开发人员、架构师和业务利益相关者都需要一个具体的机制来创建、操作和查询数据。也就是说,我们需要一种查询语言。

到目前为止,开发人员和数据架构师使用的查询语言(即 sql)过于神秘和深奥,业务决策者无法理解。但正如图形数据库 让外行人更容易理解建模过程 一样,图形数据库查询语言也让普通人比以往任何时候都更容易理解和创建自己的查询。

为什么语言效率很重要

如果您不是技术人员,您可能想知道为什么数据库查询语言很重要。毕竟,如果查询语言与自然人类语言有任何相似之处,那么它们不应该能够最终通过一些措辞上的差异来传达相同的观点吗?答案是肯定的,也不是。

让我们考虑一个自然语言的例子。在英语中,你可能会说,“我过去常常喜欢餐后谈话”,同时回忆起你的童年。在西班牙语中,同样的短语写为“ disfrutaba sobremesa。 ” 两种语言都表达了相同的想法,但其中一种语言的交流效率要高得多。

当谈到查询语言时,效率语言学是相似的。 sql 中的单个查询可以比图形数据库查询语言(如 cypher) 中的相同 查询长很多行 。 (这是 从自然语言到密码的有效映射 的一个很好的例子。)

冗长的查询不仅需要更多的运行时间,而且由于其复杂性,它们也更有可能包含人为编码错误。此外,更短的查询会增加您的开发团队的理解和维护的便利性。例如,想象一下,如果外部开发人员不得不从一个复杂的查询中挑选出来并试图弄清楚原始开发人员的意图——麻烦肯定会接踵而至。

但是我们在谈论 sql 查询和图形查询之间的效率提升水平是多少?一个比另一个效率 高多少 ?答案: 足够快,足以对您的业务产生重大影响

图查询的效率意味着它们是实时运行的,在 以一条推文的速度 运行的经济体中,这是一个你不能忽视的底线差异。

建模和查询之间的密切关系

在深入研究下面的图形数据库查询语言的机制之前,值得注意的是,查询语言不仅仅是 询问 (也称为查询)数据库以获取一组特定的结果;这也是关于首先对数据 建模的

我们从之前的文章中了解到, 图形数据库的数据建模 就像在白板上连接圆圈和线条一样简单。您在白板上绘制的内容就是您存储在数据库中的内容。

就其本身而言,这种易于建模的方式有很多商业利益,其中最明显的是您可以了解您的数据库开发人员到底在创建什么。但还有更多: 使用正确的查询语言构建的 直观模型可确保您构建数据的方式与分析数据的方式之间没有不匹配。

查询语言紧密地代表了它的模型。这就是为什么 sql 都是关于表和连接的,而 cypher 是关于实体之间的关系的。图形模型使用起来更自然,cypher 也是如此,因为它借鉴了用箭头连接的圆圈的图形表示,即使是孩子也能理解。

在关系数据库中,数据建模过程目前是从实际的日常 sql 查询中抽象出来的,因此分析和实现之间存在很大差异。换句话说,构建关系数据库模型的过程不适合从同一模型有效地提问(和回答)问题。

另一方面,图形数据库模型不仅可以传达数据的相关性,还可以帮助您清楚地传达您想对数据模型提出的各种问题。图 模型 和图 查询 只是同一枚硬币的两面。

正确的数据库查询语言可以帮助我们遍历双方。

图数据库查询语言 cypher 简介

现在是深入细节的时候了。虽然大多数关系数据库使用某种形式的 sql 作为它们的查询语言,但图形数据库世界更加多样化,因此我们将专门研究一种图形数据库查询语言:cypher。

虽然目前特定于 neo4j ,但 cypher 将图形表示为图表的密切关系使其成为描述图形的理想选择。 cypher 可以说是最容易学习的图形查询语言,一旦你理解了 cypher,就可以很容易地扩展和学习其他图形查询语言。

本介绍不是 cypher 的参考文档 ,而只是一个高级概述。

cypher 旨在让开发人员、数据库专业人员和业务利益相关者等轻松阅读和理解。它易于使用,因为它符合我们使用图表直观描述图形的方式。

cypher 的基本概念是它允许您要求数据库查找与特定模式匹配的数据。通俗地说,我们可能会要求数据库“找到像这样的东西”,而我们描述“像这样的东西”是什么样子的方式是使用 ascii 艺术 画出它们。

考虑下图中的简单模式。



这个图表描述了三个共同的朋友。

如果我们想用密码来表达这个基本图的模式,我们会写:


 (emil)<-[:knows]-(jim)-[:knows]->(ian)-[:knows]->(emil)

这个 cypher 语句描述了一条路径,它形成一个三角形,将我们称为 jim 节点连接到我们称为 ian emil 的两个节点,并且还将 ian 节点连接到 emil 节点。如您所见,Cypher 自然遵循我们在白板上绘制图形的方式。

现在,虽然这个密码模式描述了一个简单的图形结构,但它还没有引用数据库中的任何特定数据。要将模式绑定到现有数据集中的特定节点和关系,我们首先需要指定一些属性值和节点标签,以帮助在数据集中定位相关元素。

这是我们更充实的查询:


 (emil)<-[:knows]-(jim)-[:knows]->(ian)-[:knows]->(emil)

在这里,我们使用其名称属性和人员标签将每个节点绑定到其标识符。例如,emil 标识符绑定到数据集中具有标签 person 和值为 emil 的 name 属性的节点。以这种方式将部分模式锚定到真实数据是正常的密码实践。

密码子句初学者指南

(免责声明:本节仍然面向初学者,但它绝对是面向开发人员的。如果您只是对一般的数据库查询语言感到好奇,请跳到下面的“其他查询语言”部分以获得很好的总结。)

与大多数查询语言一样,cypher 由子句组成。

最简单的查询由一个匹配子句和一个返回子句组成。这是一个密码查询示例,它使用这三个子句来查找名为 jim 的用户的共同朋友


 (emil)<-[:knows]-(jim)-[:knows]->(ian)-[:knows]->(emil)

让我们更详细地看一下每个子句:

匹配

match 子句是大多数密码查询的核心。

使用 ascii 字符表示节点和关系,我们绘制我们感兴趣的数据。我们用括号绘制节点,就像上面查询中的这些示例一样:


 (emil)<-[:knows]-(jim)-[:knows]->(ian)-[:knows]->(emil)

我们使用带有大于号或小于号( --> <-- )的破折号对来绘制关系,其中 < > 号表示关系方向。在破折号之间,关系名称用方括号括起来并以冒号为前缀,就像上面查询中的这个例子一样:


 (emil)<-[:knows]-(jim)-[:knows]->(ian)-[:knows]->(emil)

节点标签也以冒号为前缀。正如您在查询的第一个节点中看到的,person 是适用的标签。


 (emil)<-[:knows]-(jim)-[:knows]->(ian)-[:knows]->(emil)

然后在大括号内指定节点(和关系)属性键值对,如本例所示:


 (emil)<-[:knows]-(jim)-[:knows]->(ian)-[:knows]->(emil)

在我们最初的示例查询中,我们正在寻找一个标记为 person 的节点,其 name 属性的值为 jim 。此查找的返回值绑定到标识符 a 。这个标识符允许我们在查询的其余部分引用代表 jim 的节点。

值得注意的是,这种模式


 (emil)<-[:knows]-(jim)-[:knows]->(ian)-[:knows]->(emil)

从理论上讲,在我们的图形数据中可能会多次出现,尤其是在大型用户集中。

为了限制查询,我们需要将查询的一部分锚定到图中的一个或多个位置。在指定我们正在寻找名称属性值为 jim 的标记为 person 的节点时,我们已将该模式绑定到图中的特定节点——表示 jim 的节点。

然后,cypher 根据提供的关系和相邻节点信息,将模式的其余部分与紧邻该锚点的图形进行匹配。这样做时,它会发现要绑定到其他标识符的节点。当 a 将始终锚定到 jim 时,b 和 c 将在查询执行时绑定到一系列节点。

返回

该子句指定应将匹配数据中的哪些表达式、关系和属性返回给客户端。在我们的示例查询中,我们有兴趣返回绑定到 b 和 c 标识符的节点。

其他密码子句

您可以在密码查询中使用的其他子句包括:

在哪里

提供过滤模式匹配结果的标准。

创造 创造独特

创建节点和关系。

合并

通过重新使用与提供的谓词匹配的现有节点和关系,或者通过创建新的节点和关系,确保提供的模式存在于图中。

删除/删除

删除节点、关系和属性。

设置属性值和标签。

订购方式

将结果作为返回的一部分进行排序。

跳过限制

跳过顶部的结果并限制结果的数量

foreach

对列表中的每个元素执行更新操作。

联盟

合并来自两个或多个查询的结果。

链接后续查询部分并将结果从一个转发到下一个。类似于 unix 中的管道命令。


如果这些子句看起来很眼熟——尤其是如果您是一名 sql 开发人员——那就太好了! cypher 旨在使 sql 老手易于学习,同时也易于初学者使用。 ( 单击此处获取最新的密码参考卡 ,以更深入地了解密码查询语言。)

同时,cypher 的不同之处足以强调我们处理的是图,而不是关系集。

其他查询语言

cypher 不是唯一的图形数据库查询语言;其他图形数据库也有自己的数据查询方式。许多,包括 neo4j,支持 rdf 查询语言 sparql 和命令式的、基于路径的查询语言 gremlin

结论

并不是每个人都在日常级别上亲身体验他们的数据库查询语言;但是,您的杂草开发团队需要一种实用的方法来建模和查询数据,尤其是当他们正在处理 基于图形的问题 时。

如果您的团队来自 sql 背景,那么像 cypher 这样的查询语言将很容易学习,甚至更容易执行。当谈到您的企业级应用程序时,您会很高兴支持它的语言是为速度和效率而构建的。


编者按:这篇文章最初出现在 bryce merkl sasaki 撰写的 neo4j 博客上。