From 3fd49bd9f03a763f0c5546277556d6b07fa4f380 Mon Sep 17 00:00:00 2001 From: Lin_qiang <1667704220@qq.com> Date: Wed, 23 Apr 2025 17:12:24 +0800 Subject: [PATCH] Apache AGE for lite openGauss document --- .../zh/docs/DataVec/Apache-AGE-Adaptation.md | 336 ++++++++++++++++++ .../zh/docs/DataVec/Gallery-Engine-AGE.md | 163 +++++++++ .../DataVec/figures/doc_img_AGE-think.png | Bin 0 -> 34877 bytes content/docs-lite/zh/menu/index.md | 2 + 4 files changed, 501 insertions(+) create mode 100644 content/docs-lite/zh/docs/DataVec/Apache-AGE-Adaptation.md create mode 100644 content/docs-lite/zh/docs/DataVec/Gallery-Engine-AGE.md create mode 100644 content/docs-lite/zh/docs/DataVec/figures/doc_img_AGE-think.png diff --git a/content/docs-lite/zh/docs/DataVec/Apache-AGE-Adaptation.md b/content/docs-lite/zh/docs/DataVec/Apache-AGE-Adaptation.md new file mode 100644 index 000000000..f0ad9cf4c --- /dev/null +++ b/content/docs-lite/zh/docs/DataVec/Apache-AGE-Adaptation.md @@ -0,0 +1,336 @@ +# Apache AGE (incubating) for openGauss 适配详情 + +## 说明 +Apache AGE通过创建插件的形式使用。 +``` +create extension age; +``` +AGE安装之后,会默认创建ag_catalog的schema,AGE内置的数据类型、函数均存储在ag_catalog下。因此在使用AGE的时候,特别是执行cypher语句时,需要先执行命令: +``` +SET search_path TO ag_catalog; +``` +同时需要执行 load 'age' 命令确保age插件的全部hook被加载,保证图数据的完整性。 +``` +load 'age'; +``` +## 1. 图的操作 +图由一组顶点和边组成,其中每个单独的节点和边都具有属性映射。顶点是图的基本对象,它可以独立于图中的其他任何东西而存在。边在两个顶点之间创建有向连接。 +### 1.1 创建图 +创建图使用函数:create_graph(graph_name); +``` +SELECT * FROM ag_catalog.create_graph('graph_name'); +``` +### 1.2 删除图 +删除图使用函数:drop_graph(graph_name, cascade); +``` +SELECT * FROM ag_catalog.drop_graph('graph_name'); +``` +### 1.3 创建图中的点类型 +创建图中的点类型使用函数:create_vlabel(graph_name, label_name); +``` +SELECT * FROM ag_catalog.create_vlabel('graph_name','label_name'); +``` +每当使用create_vlabel()函数创建顶点标签时,会在new_graph的命名空间new_graph中生成一个新表""。用于创建边类型的create_elabel()函数也是如此。这两个函数不是必须使用的,用Cypher语句创建顶点和边时,如果类型表不存在,会自动创建。 + +### 1.4 创建图中的边类型 +创建图使用函数:create_elabel(graph_name, label_name); +``` +SELECT * FROM ag_catalog.create_elabel('graph_name','label_name'); +``` + +## 2. 图的存储 +### 2.1 图 +图创建之后,内核会创建一个与图名称相同的schema。同时在ag_catalog.ag_graph的表中会插入一条数据,标记新创建的schema用来存储图数据。 +``` +SELECT create_graph('new_graph'); + +NOTICE: graph "new_graph" has been created + create_graph +-------------- + +(1 row) + +SELECT * FROM ag_catalog.ag_graph; + + name | namespace +-----------+----------- + new_graph | new_graph +(1 row) +``` +### 图中的点和边 +``` +-- 创建图之后,会在该图对应的schema中创建_ag_label_vertex和_ag_label_edge两张表作为默认的点表和边表,同时会在ag_catalog.ag_label中插入两条数据将点表和边表与schema关联起来。 +SELECT * FROM ag_catalog.ag_label; + + name | graph | id | kind | relation +------------------+-------+----+------+---------------------------- + _ag_label_vertex | 68484 | 1 | v | new_graph._ag_label_vertex + _ag_label_edge | 68484 | 2 | e | new_graph._ag_label_edge +(2 rows) + +-- 创建点表 +SELECT create_vlabel('new_graph', 'Person'); +NOTICE: VLabel "Person" has been created + create_vlabel +--------------- + +(1 row) + +-- 创建点表之后,会在ag_catalog.ag_label表中插入一条数据将点表与图关联起来。kind为v代表点表kind为e代表边表 +SELECT * FROM ag_catalog.ag_label; + name | graph | id | kind | relation +------------------+-------+----+------+---------------------------- + _ag_label_vertex | 68484 | 1 | v | new_graph._ag_label_vertex + _ag_label_edge | 68484 | 2 | e | new_graph._ag_label_edge + Person | 68484 | 3 | v | new_graph."Person" +(3 rows) +``` + +## 3. Cypher查询 +Cypher语句无法在数据库中直接执行。需要通过cypher()函数构造,将Cypher语句作为cypher()函数的参数执行,cypher()函数返回一个SETOF records。 +### 3.1 cypher()函数介绍 +cypher(graph_name, query_string, parameters) +> 第一个参数graph_name为要查询的图,第二个参数query_string为Cypher语句,第三个参数parameters为可选参数只能与Prepared Statements一起使用。否则将抛出错误。 +``` +SELECT * FROM cypher('graph_name', $$ +/* Cypher Query Here */ +$$) AS (result1 agtype, result2 agtype); +``` +**注意事项** +> 1. AS 后的 (result1 agtype, result2 agtype) 即SETOF records 需要和Cypher语句中的返回值个数相同 +> 2. SELECT * FROM cypher 不能写成 SELECT cypher +> 3. 执行语句前需要执行 load 'age' 和 set search_path = ag_catalog + +## 数据类型及函数说明 +以下对AGE中包含的数据类型、Cypher语法、函数进行简要说明。 +### 1 数据类型 +AGE的会创建两种数据类型: graphid 和 agtype。其中graphid代表点和边的唯一id标识符。agtype为AGE的核心数据类型,具体介绍可参考 https://age.apache.org/age-manual/master/intro/types.html。 + +#### 1.1 Simple DataTypes +简单数据类型包括:Null、Integer、Float、Numeric、Bool、String。 +#### 1.2 Composite DataTypes +复合数据类型包括:List、Map。 +- List支持以下操作 + +| 序号 | 功能支持 | 说明 | +|:--------|:---------|--------:| +| 1 |List in general | 普通list | +| 2 |NULL in a List | 带null的list | +| 3 |Access Individual Elements | 获取list的某个元素 | +| 4 |MapElements in Lists | list元素包含map结构 | +| 5 |Accessing Map Elements in Lists | 获取list元素中map的值 | +| 6 |Negative Index Access | 负值索引 | +| 7 |Index Ranges | 区间索引 | +| 8 |Negative Index Ranges | 负值区间区间索引 | +| 9 |Positive Slices | 正切片操作 | +| 10 |Negative Slices | 负切片操作 | + +- Map支持以下操作 + +| 序号 | 功能支持 | 说明 | +|:--------|:---------|--------:| +|1 | Literal Maps with SimpleDataTypes | 普通map类型 | +|2 | Literal Maps with composite Data Types | map中包含复合数据类型 | +|3 | Property Access of a map | map的属性值获取操作 | +|4 | Accessing List Elements in Maps | map中获取list元素操作 | + +#### 1.3 Simple Entities +简单实体类型包括 GraphId、Labels、Properties。又简单实体类型组成Vertex、Edge、Composite Entities。 + +#### 1.4 Vertex +Vertex 是图的基本组成元素,代表节点。 + +#### 1.5 Edge +Edge 是图的基本组成元素,代表边。 + +#### 1.6 Composite Entities +由Vertex 和 Edge组成的Path类型。 + +### 2 Cypher语法 +AGE对Cypher语法的支持具体介绍可参考:https://age.apache.org/age-manual/master/clauses/match.html + +#### 2.1 Match +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 | get all vertices | 获取全部节点| +|2 | get all vertices with a label | 获取某label类型的全部节点| +|3 | related vertices | 通过边获取相关节点(邻居节点)| +|4 | match with labels | 通过label过滤相关节点| +|5 | Outgoing Edges |有向边支持| +|6 | Directed Edges and variable | 有向边变量支持| +|7 | Match on edge type |通过label type过滤边| +|8 | Match on edge type and use a variable | 通过label type过滤边同时设置变量| +|9 | Multiple Edges | 多条边匹配| +|10 | Variable Length Edges | 变长路径匹配| + +#### 2.2 With +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |Filter on aggregate function results |通过聚合函数过滤结果| +|2 |Sort results before using collect on them |collect前排序操作| +|3 |Limit branching of a path search |匹配路径、限制为一定数量,然后使用这些路径作为基础再次匹配| + +#### 2.3 SKIP +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |skip first three rows |跳过最开始的行| +|2 |Return middle tow rows |配合limit返回中间的行| +|3 |Using an expression with SKIP to return a subset of the rows |使用SKIP带有表达式返回行的子集| + +#### 2.4 LIMIT +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |Return a subset of the rows |返回查询结果的子集| +|2 |Using an expression with LIMIT to return a subset of the rows |limit带有表达式返回行的子集| + +#### 2.5 Return +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 | Return nodes |返回查询的节点| +|2 | Return edges |返回查询的边| +|3 | Return property |返回节点或者边的属性| +|4 | Return all elements |返回全部元素| +|5 | Variable with uncommon characters |支持不通用的字符变量| +|6 | Aliasing a field |返回值起别名| +|7 | unique results |distinct 返回值| + +#### 2.6 ORDER BY +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 | Order nodes by proerty |通过单个属性排序| +|2 | Order nodes by multiple properties |通过多个属性排序| +|3 | Order nodes in descending order |降序排序| +|4 | Ordering null |null的排序规则升序在最后| + +#### 2.7 CREATE +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +| 1 | Create single vertex |创建单个节点| +| 2 | Create multiple vertices |创建多个节点| +| 3 | Create a vertex with a label |创建带标签的节点| +| 4 | Create vertex and add labels and properties |创建带标签和加属性的节点| +| 5 | Return create node |创建并返回节点| +| 6 | Create an edge between two nodes |创建边| +| 7 | Create an edge and set properties |创建边并赋属性值| +| 8 | Create a full path |创建一条路经| + +#### 2.8 SET +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |Set a property |修改单个属性| +|2 |Return created vertex |返回修改后的节点| +|3 |Remove a property |移除属性| +|4 |Set multiple properties using one SET clause |修改多个属性| + +#### 2.9 REMOVE +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |Remove a property |移除属性| + +#### 2.10 DELETE +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |Delete single vertex |删除单个节点| +|2 |Delete all vertices and edges |删除全部节点和边| +|3 |Delete edges only |删除边| +|4 |Return a deleted vertex |返回删除的节点| + +### 3 函数支持 +函数主要是对agtype的操作和表达式的生成,具体内容可参考:https://age.apache.org/age-manual/master/functions/predicate_functions.html + +#### 3.1 Predicate Functions +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |Exists(Property) |检测属性是否存在| +|2 |Exists(Path) | 检测查询路径是否存在| + +#### 3.2 Scalar Functions +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |id |返回顶点或边的 id| +|2 |start_id |返回边的起始顶点的 id| +|3 |end_id |返回边的终止顶点的 id| +|4 |type |返回边类型的字符串表示形式| +|5 |properties |返回包含顶点或边的所有属性的 agtype map。如果参数已经是map,则原封不动地返回| +|6 |head |返回 agtype 列表中的第一个元素| +|7 |last |返回 agtype 列表中的最后一个元素| +|8 |length |返回路径的长度| +|9 |size |返回列表的长度| +|10 |startNode |返回边的起始节点| +|11 |endNode |返回边的终点节点| +|12 |timestamp |返回当前时间与 UTC 1970 年 1 月 1 日午夜之间的差值(以毫秒为单位)| +|13 |toBoolean |将字符串值转换为布尔值| +|14 |toFloat |将整数或字符串值转换为浮点数| +|15 |toInteger |将浮点数或字符串值转换为整数值| +|15 |coalesce |返回给定表达式列表中的第一个非空值| + +#### 3.3 List Functions +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |keys |返回一个列表,其中包含顶点、边或map的所有属性名称的字符串表示形式| +|2 |range |返回一个列表,该列表包含起始值start和结束值end所限定范围内的所有整数值| +|3 |labels |返回一个包含节点所有标签的字符串表示形式的列表| +|4 |relationships |返回包含路径中所有关系的列表| +|5 |nodes |返回包含路径中所有顶点的列表| + +#### 3.4 Numeric Functions +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |rand |返回一个随机浮点数,范围从 0(含)到 1(不含);即 [0,1]| +|2 |abs |返回给定数字的绝对值| +|3 |ceil |返回大于或等于给定数字且等于数学整数的最小浮点数| +|4 |floor |返回小于或等于给定数字且等于数学整数的最大浮点数| +|5 |round |返回四舍五入为最接近的整数的给定数字的值| +|6 |sign |返回给定数字的符号| + +#### 3.5 Logarithmic Functions +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |e |返回自然对数的底数,e| +|2 |sqrt |返回数字的平方根| +|3 |exp |返回 e^n,其中 e 是自然对数的底数,n 是参数表达式的值| +|4 |log |返回数字的自然对数| +|5 |log10 |返回一个数字的常用对数(底数为 10)| + +#### 3.6 Trigonometric Functions +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |degrees |将弧度转换为度| +|2 |radians |将度数转换为弧度| +|3 |pi |返回数学常数 pi| +|4 |sin |返回数字的正弦| +|5 |cos |返回数字的余弦| +|6 |tan |返回数字的正切| +|7 |cot |返回数字的余切| +|8 |asin |返回数字的反正弦| +|9 |acos |返回数字的反余弦| +|10| atan |返回数字的反正切| +|11| atan2 |以弧度返回一组坐标的反正切值| + +#### 3.7 String Functions +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |replace |返回一个字符串,其中原始字符串中出现的所有指定字符串都已被另一个(指定的)字符串替换 +|2 |split |返回根据给定分隔符的匹配项对原始字符串进行拆分后得到的字符串列表| +|3 |left |返回包含原始字符串最左边指定数量字符的字符串。| +|4 |right |返回包含原始字符串最右边指定数量字符的字符串。| +|5 |substring |返回原始字符串的子字符串,以从 0 开始的索引开始和长度。| +|6 |rTrim |返回删除尾随空格后的原始字符串| +|7 |lTrim |返回删除前导空格后的原始字符串。| +|8 |trim |返回删除前导和尾随空格的原始字符串| +|9 |toLower |以小写形式返回原始字符串| +|10 |toUpper |以大写形式返回原始字符串| +|11 |reverse |返回原始字符串中所有字符的顺序均已反转的字符串。| + +#### 3.8 Aggregation Functions +| 序号 | 功能支持 | 说明 | +|:--------|:---------|:--------| +|1 |min |返回一组值中的最小值| +|2 |max |返回一组值中的最大值| +|3 |stDev |返回给定值在一组中的标准偏差| +|4 |stDevP |返回给定值在一组中的标准偏差| +|5 |percentileCont |返回给定值在组中的百分位数| +|6 |percentileDisc |返回给定值在组中的百分位数| +|7 |count |返回值或记录的数量| +|8 |avg |返回一组数值的平均值| +|9 |sum |返回一组数值的总和| \ No newline at end of file diff --git a/content/docs-lite/zh/docs/DataVec/Gallery-Engine-AGE.md b/content/docs-lite/zh/docs/DataVec/Gallery-Engine-AGE.md new file mode 100644 index 000000000..a8ac54cdb --- /dev/null +++ b/content/docs-lite/zh/docs/DataVec/Gallery-Engine-AGE.md @@ -0,0 +1,163 @@ +# Apache AGE (incubating) for openGauss + +## 介绍 +图数据库由于能够处理数据之前的复杂关系,近年来得到了广泛的应用。与传统关系型数据库不同,图数据库将数据表示为节点、边和属性。节点表示实体,边表示实体之间的关系,属性表示两者的属性。 + +Apache AGE是基于PostgreSQL开发的图数据库引擎,AGE的所有组件都运行在PostgreSQL事务缓存层和存储层之上,AGE实现了一个存储引擎同事处理关系型和图数据模型,用户可使用标准的ANSI SQL和图查询语言openCypher对数据进行查询。 + +Apache AGE在数据库内核的查询解析,查询重写,查询计划,查询执行,数据存储均有涉及,数据存储方面定义了图数据库的存储模型。openGauss在其他方面使用数据库内核的hook点,对Cypher语言进行了支持,实现了同事处理关系型和图数据的能力。 + + +
+ +
+ +openGauss数据库使用插件的方式支持图数据库引擎,在openGauss数据库中可直接采用创建插件的方式使用Apache AGE的能力。 + +## 安装 + +> 轻量版的openGauss镜像,已安装AGE,部署好openGauss数据库后,通过加载插件方式可直接使用图数据库能力 + +### 编译安装 + +age源码地址:https://gitee.com/opengauss/Plugin/tree/master/contrib/age + +#### 方式一(同openGauss一起安装) +将age源码放到openGauss-server源码的contrib目录下,直接编译安装openGauss-server,age会自动编译安装 +> 此方式适用于openGauss-server同时编译安装 + +#### 方式二(使用openGauss源码安装) +1. 将age源码 放到openGauss-server的源码 contrib 目录下 +2. 进入 contrib/age 目录,在age的目录下执行 make install +> 此方式适用于openGauss-servery已经使用源码编译安装, 并且源码及编译环境依旧保存,可以使用此方式安装age + +#### 安装方式三(使用PGXS安装) +1. 安装必要依赖 +``` +yum install gcc glibc glib-common readline readline-devel zlib zlib-devel flex bison perl +``` +> gcc 版本需要>=7.3.0 +2. 需要将openGauss安装目录的bin目录配置到环境变量中 执行命令 +``` +which pg_config +``` +确认pg_config 是 openGauss 安装目录下的 pg_config
+3. 进入age根目录 执行 +``` +make install USE_PGXS=true +``` +> 此方式适用于直接使用安装包安装openGauss的方式。这里不建议使用PGXS安装方式, 随着openGauss的升级,必要的头文件不会全部安装到安装目录,因此会存在编译时缺少头文件的问题,可以按照错误提示从openGauss的 头文件拷贝到openGauss安装目录include/postgresql/server/ 文件夹下 + +##### 安装必要的依赖 +> 前提条件:openGauss正常编译安装,并且配置到了环境变量中 在age的源码目录执行命令 +``` +make install USE_PGXS=true +``` + +## 快速开始 + +### 连接openGauss +``` +gsql -r +``` + +### 创建插件 + +- 执行命令 +``` +create extension age; +``` +- 示例 +``` +openGauss=# create extension age; +CREATE EXTENSION +``` + +- 约束 + +openGauss安装dolphin插件后,B模式下需要使用如下方式安装AGE插件: +``` +set dolphin.b_compatibility_mode=off; +create extension age; +set dolphin.b_compatibility_mode=on; +``` + +### 设置查询空间 +- 说明 + +AGE安装之后,会默认创建ag_catalog的schema,AGE内置的数据类型、函数均存储在ag_catalog下。 +- 执行命令 +``` +SET search_path TO ag_catalog; +``` +- 示例 +``` +openGauss=# SET search_path TO ag_catalog; +SET +``` + +### 加载插件 +- 执行命令 +``` +load 'age'; +``` +- 示例 +``` +openGauss=# load 'age'; +LOAD +``` + +### 创建图空间 +- 执行命令 +``` +SELECT create_graph('test'); +``` +- 示例 +``` +openGauss=# SELECT create_graph('test'); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "_ag_label_vertex_pkey" for table "_ag_label_vertex" +CONTEXT: referenced column: create_graph +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "_ag_label_edge_pkey" for table "_ag_label_edge" +CONTEXT: referenced column: create_graph +NOTICE: graph "test" has been created +CONTEXT: referenced column: create_graph + create_graph +-------------- + +(1 row) +``` + +### 执行cypher语句 +- 语法 +``` +SELECT * FROM cypher(参数1 要查询的图空间, 参数2 cypher语句) AS (a agtype ,[返回元组的个数]); +``` +- 示例 +``` +openGauss=# SELECT * FROM cypher('test', $$CREATE (:v {i: 0})$$) AS (a agtype); +a +--- +(0 rows) + +openGauss=# SELECT * FROM cypher('test', $$MATCH (n:v) RETURN n$$) AS (n agtype); +n +----------------------------------------------------------------------- +{"id": 844424930131969, "label": "v", "properties": {"i": 0}}::vertex +(1 row) +``` + +## 适配情况 +AGE在openGauss上实现了适配,适配详情参考 [Apache AGE适配openGauss详情说明](Apache-AGE-Adaptation.md) + +- 更多资料 +> 更详细的使用方式可以参考AGE的官方文档: https://age.apache.org/age-manual/master/ + +## Apache AGE回归测试语句运行 + +### 执行步骤 +> 前提条件:openGauss使用源码编译的方式安装 +1. 将age源码放在openGauss源码的contrib目录下 +2. 进入age源码目录,执行命令 +``` +make installcheck +``` diff --git a/content/docs-lite/zh/docs/DataVec/figures/doc_img_AGE-think.png b/content/docs-lite/zh/docs/DataVec/figures/doc_img_AGE-think.png new file mode 100644 index 0000000000000000000000000000000000000000..95b1ce5c384a075e8b5eb2f3dcb9fc870f4f4691 GIT binary patch literal 34877 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

)eG?uP4!x?_EQm2;tVJ1Jju3ucpX4f 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 d`9B}~_)B#*FXNH>X;4-IAt$YbEtE3w`Ck}}}) - [Spring Boot集成openGauss DataVec实现向量化检索]({{< relref "./docs/DataVec/openGauss-Springboot.md" >}}) - [openGauss AGEGraph + 大模型实现 GraphRAG,助力更强 RAG]({{< relref "./docs/DataVec/openGauss-AGEGraph.md" >}}) + - [图数据库引擎]({{< relref "./docs/DataVec/Gallery-Engine-AGE.md" >}}) + - [适配详情]({{< relref "./docs/DataVec/Apache-AGE-Adaptation.md" >}}) - [安全加固指南]({{< relref "./docs/SecHarden/secHarden.md" >}}) - [数据库加固概述]({{< relref "./docs/SecHarden/数据库加固概述.md" >}}) - [安全配置规范基线]({{< relref "./docs/SecHarden/安全配置规范基线.md" >}}) -- Gitee