polar_age增强版

更新时间:
复制 MD 格式

polar_age插件允许您在PolarDB PostgreSQL版集群中直接处理和分析图数据。对于需要在关系型数据库中融合图模型分析的场景,该插件提供了一个高性能的解决方案,使您无需迁移数据到专门的图数据库,即可使用Cypher查询语言进行复杂的关联分析。

适用范围

您的集群数据库引擎需为:PostgreSQL 16。

功能优势

polar_age是PolarDB基于开源Apache AGE社区版进行功能增强和性能优化的图数据库插件,与开源版本相比,具备以下优势:

  • 更大的存储容量:支持64位GraphID。

  • 数据生命周期管理:支持为节点和边设置生存时间(TTL)。

  • 灵活的属性定义:支持在图(Graph)的节点和边上定义自定义属性字段。

  • 强大的融合分析能力:支持在Cypher查询中结合其他插件(如向量插件)进行多模融合检索。

  • 高级查询方式:支持多标签(Multi-Label)查询,提升复杂图谱的查询灵活性。

  • 统一的数据管理:支持通过SQL对图数据执行增删改查(CRUD)操作。

  • 加速向量分析:支持多向量索引,加速图与向量数据的融合分析。

  • 全套图算法和图计算一站式:内置 11 个图算法函数(涵盖可达性、最短路径、中心性、连通性、社区发现、三角形计数与图嵌入),可直接在 SQL 中调用,无需导出数据到外部计算引擎。

安装与配置插件

安装插件

在您的数据库中安装polar_age插件。如果您尚未创建插件,请使用高权限账号执行以下命令:

CREATE EXTENSION polar_age;

配置数据库

  • (推荐)为数据库设置永久生效:通过修改数据库级别的参数,使任何新建立的连接都能自动加载polar_age扩展并设置好搜索路径,无需在每次连接会话时手动配置。

    -- 将 ag_catalog 添加到默认搜索路径
    ALTER DATABASE <your_db_name> SET search_path = "$user", public, ag_catalog, pg_catalog;
    
    -- 将 polar_age 添加到会话预加载库,实现自动初始化
    ALTER DATABASE <your_db_name> SET session_preload_libraries = 'polar_age';
    重要
    • 请将<your_db_name>替换为您的实际数据库名称。

    • 使用数据管理 DMS(Data Management)客户端设置search_path时,可能会存在兼容性问题,您可使用PolarDB-Tools执行相关语句。

  • 在当前会话中临时生效:仅对当前数据库连接会话有效,适用于临时测试或调试。断开连接后配置即失效。

    SET search_path = "$user", public, ag_catalog, pg_catalog;
    重要

    使用数据管理 DMS(Data Management)客户端设置search_path时,可能会存在兼容性问题,您可使用PolarDB-Tools执行相关语句。

配置普通用户权限

  • 授予USAGE权限给所需的普通用户:

    GRANT USAGE ON SCHEMA ag_catalog TO <your_db_user>;
    GRANT ALL ON ag_catalog.ag_graph TO <your_db_user>;
    GRANT ALL ON ag_catalog.ag_label TO <your_db_user>;
  • 若用户仅为RW用户,需要额外授予创建表的CREATE权限。

    GRANT CREATE ON DATABASE <your_db_name> TO <your_db_user>;

快速入门

本教程将引导您完成从初始化扩展到执行第一个Cypher查询的全过程。

  1. 为数据库安装polar_age插件,并将其配置为自动加载,确保每次连接后都能直接使用Cypher查询。

    -- 创建 polar_age 扩展
    CREATE EXTENSION polar_age;
    
    -- 将 polar_age 加入会话预加载库,并设置默认搜索路径
    ALTER DATABASE <your_db_name> SET search_path = "$user", public, ag_catalog, pg_catalog;
    ALTER DATABASE <your_db_name> SET session_preload_libraries = 'polar_age';
  2. 创建一个图来组织和存储您的图数据。

    SELECT ag_catalog.create_graph('social_network');
  3. 创建点与边。

    -- 点
    SELECT create_vlabel('social_network', 'Person');
    -- 边
    SELECT create_elabel('social_network', 'Knows');
  4. 向图中写入数据:创建代表人物的节点(Node)和代表关系的边(Edge)。

    -- 向 "social_network"."Person" 表中批量写入两个人物点
    INSERT INTO "social_network"."Person" (id, properties) VALUES 
    (ag_catalog._make_graph_id('social_network', 'Person', 'alice'::cstring), '{"name": "alice", "age": 30}'::agtype),
    (ag_catalog._make_graph_id('social_network', 'Person', 'bob'::cstring), '{"name": "bob", "age": 40}'::agtype);
    
    -- 在 'alice' 和 'bob' 之间创建一条 "Knows" 关系
    INSERT INTO "social_network"."Knows" (id, start_id, end_id, properties)
    VALUES (
        ag_catalog._next_graph_id('social_network', 'Knows'),                     -- 生成边的自增ID
        ag_catalog._make_graph_id('social_network', 'Person', 'alice'::cstring),  -- 起始点ID
        ag_catalog._make_graph_id('social_network', 'Person', 'bob'::cstring),    -- 终止点ID
        '{"since": 2022}'::agtype                                                 -- 边的属性
    ); 
  5. 验证数据写入成功并执行图查询。

    1. 使用SQL查询所有Person:

      SELECT id, properties FROM "social_network"."Person";
        id   |          properties          
      -------+------------------------------
       3_xxx | {"age": 30, "name": "alice"}
       3_xxx | {"age": 40, "name": "bob"}
    2. 使用SQL查询名为bob的Person:

      SELECT id, properties FROM "social_network"."Person" WHERE agtype_access_operator(VARIADIC ARRAY[properties, '"name"'::agtype]) = '"bob"'::agtype;
        id   |          properties          
      -------+------------------------------
       3_xxx | {"age": 40, "name": "bob"}
    3. 使用Cypher查找所有关系。

      SELECT * FROM cypher('social_network', $$
          MATCH (p1:Person)-[k:Knows]->(p2:Person)
          RETURN p1.name, type(k), p2.name, k.since
      $$) AS (start_node_name agtype, relationship_type agtype, end_node_name agtype, since agtype);
       start_node_name | relationship_type | end_node_name | since 
      -----------------+-------------------+---------------+-------
       "alice"         | "Knows"           | "bob"         | 2022

多模检索

polar_age 支持在 Cypher 中对图、向量、全文以及时空数据进行统一检索。以下分别给出图+向量、图+全文两个示例。

图 + 向量

  1. 安装向量插件:

    CREATE EXTENSION vector;
  2. 创建一个新图,并在表上新增一个名为 embedding 的向量列(维度为 3):

    SELECT create_graph('vec_graph');
    ALTER TABLE vec_graph._ag_label_vertex ADD COLUMN "embedding" VECTOR(3);
    
    -- 创建 Person 的点类型
    SELECT create_vlabel('vec_graph', 'person');
    说明

    向量字段也可以是通过 polar_ai 插件作为 GENERATED ALWAYS 的列自动生成,解决数据不一致的问题:

    CREATE EXTENSION polar_ai;
    
    ALTER TABLE hy_graph._ag_label_vertex ADD COLUMN "embedding" vector(3)
    GENERATED ALWAYS AS (
      polar_ai.ai_text_embedding(
        agtype_object_field_text(properties,'content'))
    ) STORED;
  3. 插入模拟数据并创建索引:

    INSERT INTO "vec_graph"."person"(id, properties, embedding)
    SELECT
        _make_graph_id('vec_graph', 'person', i),
        jsonb_build_object('id', i)::text::agtype,
        ARRAY[
            i * 0.01,
            0.5 - i / 154.0,
            1 / (i * 0.375+1.0)
        ]::vector(3)
    FROM generate_series(1, 100) AS i;
    
    CREATE INDEX vec_cosine_idx ON vec_graph.person USING hnsw(embedding vector_cosine_ops);
  • 使用 Cypher 进行向量查询:

    SELECT * FROM cypher('vec_graph', $$
      MATCH (n:person)
      RETURN n
      ORDER BY _column(n, 'embedding') OPERATOR (`<=>`) [1.0,0.87,0.44]::vector
      LIMIT 10
    $$) AS (n agtype);

    也可以直接返回向量列:

    SELECT * FROM cypher('vec_graph', $$
      MATCH (n:person)
      RETURN n, _column(n, 'embedding')
      ORDER BY _column(n, 'embedding') OPERATOR (`<=>`) [1.0,0.87,0.44]::vector
      LIMIT 20
    $$) AS (n agtype, e vector);

    也可以结合其他标量检索,例如 n.id > 5:

    SELECT * FROM cypher('vec_graph', $$
      MATCH (n:person)
      WHERE n.id > 5
      RETURN n, _column(n, 'embedding')
      ORDER BY _column(n, 'embedding') OPERATOR (`<=>`) [1.0,0.87,0.44]::vector
      LIMIT 20
    $$) AS (n agtype, e vector);

图 + 全文

  1. 安装全文检索插件:

    CREATE EXTENSION pg_jieba;
  2. 创建一个新图,并新增 properties_tsvector 列用于保存分词结果:

    SELECT create_graph('ft_graph');
    ALTER TABLE ft_graph._ag_label_vertex
    ADD COLUMN properties_tsvector tsvector DEFAULT NULL;
    
    -- 创建 page 的点类型
    SELECT create_vlabel('ft_graph', 'page');
  3. 插入模拟数据:

    INSERT INTO "ft_graph"."page"(id, properties)
    VALUES
    (_make_graph_id('ft_graph', 'page', 1), '{"content":"大模型产品解决方案文档与社区权益中心定价云市场合作伙伴支持与服务了解阿里云首页云原生数据库 PolarDB 云原生数据库 PolarDBPolarDB 是阿里巴巴自研的新一代云原生数据库,在计算存储分离架构下,利用了软硬件结合的优势,为用户提供具备极致弹性、高性能、海量存储、安全可靠的数据库服务。100%兼容 MySQL 和 PostgreSQL 生态,高度兼容 Oracle 语法。", "id": 1}'),
    (_make_graph_id('ft_graph', 'page', 2), '{"content":"PolarDB 产品系列介绍快速入门价格计算器资源包规格计算器相关技术圈 PolarDB 引擎版本 PolarDB MySQL 版多主多写、多活容灾、HTAP 特性,交易性能高达开源数据库的 6 倍,分析性能高达开源数据库的 400 倍,TCO 低于自建数据库 50%", "id": 2}'),
    (_make_graph_id('ft_graph', 'page', 3), '{"content":"PolarDB 分布式版高吞吐、大存储、低延时、易扩展和超高可用的云时代数据库服务 PolarDB PostgreSQL 版快速弹性、高性能、海量存储、安全可靠的数据库服务,支持阿里云自研 Ganos 多维多模时空信息引擎及开源 PostGIS 地理信息引擎 PolarDB PostgreSQL 版(兼容 Oracle)存储计算分离架构,软硬件结合,提供极致弹性、高性能、海量存储、安全可靠的数据库服务", "id": 3}'),
    (_make_graph_id('ft_graph', 'page', 4), '{"content":"体验教程免费云资源,真实云环境,沉浸式所见即所得体验丰富实践场景与解决方案 PolarDB MySQL Serverless 极致弹性体验 Serverless 动态弹性升降资源体验弹性过程中的无感伸缩和秒级弹升体验并观测 Serverless 的性能和价格力 PolarDB MySQL 无感秒切无需购买任何资源,真正免费体验在线体验热备无感秒切的效果", "id": 4}');
  4. 更新 properties_tsvector 字段并创建索引:

    UPDATE "ft_graph"."page"
    SET properties_tsvector = to_tsvector('jiebacfg', agtype_object_field_text(properties, 'content'));
    
    CREATE INDEX ON "ft_graph"."page" USING GIN(properties_tsvector);
  5. 混合查询:

    SELECT * FROM cypher('ft_graph', $$
      MATCH (n:page)
      WHERE _column(n, 'properties_tsvector') OPERATOR (`@@`) to_tsquery('PolarDB|PostgreSQL版|快速'::text)::tsquery
      RETURN n
    $$) AS (n agtype);

    同样也可以是“标量 + 全文”的模式:

    SELECT * FROM cypher('ft_graph', $$
      MATCH (n:page)
      WHERE n.id > 2 AND
        _column(n, 'properties_tsvector') OPERATOR (`@@`) to_tsquery('PolarDB|PostgreSQL版|快速'::text)::tsquery
      RETURN n
    $$) AS (n agtype);

图计算

polar_age 在 ag_catalog schema 下提供 11 个内置图算法函数,可直接作为表函数在 SQL 中调用。它们覆盖最常用的图分析场景:可达性、最短路径、中心性、连通性、社区发现、三角形计数与图嵌入。

pagerank

计算每个顶点的 PageRank 中心性分值。采用幂迭代法,支持个性化 PageRank(PPR)和加权 PageRank(WPR,Xing & Ghorbani 2004)。

-- 最简调用:仅指定图名,对全部顶点和边计算 PageRank
SELECT node_id, score
FROM ag_catalog.pagerank('social_graph')
ORDER BY score DESC
LIMIT 10;

-- 指定标签:只对 Person 顶点和 knows 边计算
SELECT node_id, score
FROM ag_catalog.pagerank('social_graph',
    node_label => 'Person',
    edge_label => 'knows')
ORDER BY score DESC
LIMIT 10;

-- 多标签选择:同时包含多种顶点和边类型
SELECT node_id, score
FROM ag_catalog.pagerank('social_graph',
    node_labels        => '["Person", "Organization"]'::agtype,
    relationship_types => '["knows", "works_at"]'::agtype)
ORDER BY score DESC
LIMIT 10;

-- 调整迭代参数:提高精度
SELECT node_id, score
FROM ag_catalog.pagerank('social_graph',
    damping_factor => 0.85,
    max_iterations => 100,
    tolerance      => 1e-10)
ORDER BY score DESC
LIMIT 10;

leiden

Leiden 社区发现算法(改进 Louvain,保证社区连通性),支持属性过滤、增量计算和中间层结果输出。

-- 基本用法:Leiden 社区发现
SELECT community_id, count(*) AS members,
       max(modularity) AS modularity
FROM ag_catalog.leiden('social_graph',
                       node_label => 'Person',
                       edge_label => 'knows')
GROUP BY community_id
ORDER BY members DESC
LIMIT 20;

-- 调整分辨率:gamma 越大发现越细粒度的社区
SELECT community_id, count(*) AS members
FROM ag_catalog.leiden('social_graph',
                       node_label => 'Person',
                       edge_label => 'knows',
                       gamma      => 2.0)
GROUP BY community_id
ORDER BY members DESC
LIMIT 20;

-- theta=0 确定性模式(结果可重复)
SELECT community_id, count(*) AS members
FROM ag_catalog.leiden('social_graph',
                       node_label => 'Person',
                       edge_label => 'knows',
                       theta      => 0.0)
GROUP BY community_id
ORDER BY members DESC
LIMIT 20;

-- 使用 node_filter:只对活跃用户做 Leiden 社区发现
SELECT community_id, count(*) AS members
FROM ag_catalog.leiden('social_graph',
                       node_label  => 'Person',
                       node_filter => '{"active": true}'::agtype,
                       edge_label  => 'knows')
GROUP BY community_id
ORDER BY members DESC
LIMIT 10;

-- 使用 edge_filter:只考虑强关系
SELECT community_id, count(*) AS members
FROM ag_catalog.leiden('social_graph',
                       node_label  => 'Person',
                       edge_label  => 'knows',
                       edge_filter => '{"strength": "strong"}'::agtype)
GROUP BY community_id
ORDER BY members DESC
LIMIT 10;

-- 多标签 + 增量计算
SELECT node_id, community_id
FROM ag_catalog.leiden('social_graph',
                       node_labels        => '["Person","Organization"]'::agtype,
                       relationship_types => '["knows","works_at"]'::agtype,
                       seed_property      => 'last_community',
                       max_iterations     => 5);

-- 中间层结果 + 连续 ID
SELECT node_id, community_id, intermediate_communities
FROM ag_catalog.leiden('social_graph',
                       node_label => 'Person',
                       edge_label => 'knows',
                       include_intermediate_communities => true,
                       min_community_size => 5);

node2vec

为图中的节点生成低维嵌入向量,可用于下游的相似度计算、聚类或机器学习任务。

-- 基本用法:为社交网络中的每个人生成 64 维嵌入
SELECT node_id, embedding
FROM ag_catalog.node2vec('social_graph',
    node_label          => 'Person',
    edge_label          => 'knows',
    embedding_dimension => 64)
LIMIT 10;

-- 调整 p/q 偏向 BFS(同质性,同社区节点更相似)
SELECT node_id, embedding
FROM ag_catalog.node2vec('social_graph',
    node_label          => 'Person',
    edge_label          => 'knows',
    embedding_dimension => 64,
    return_factor       => 1.0,
    in_out_factor       => 2.0);

-- 调整 p/q 偏向 DFS(结构等价性,相似角色更相似)
SELECT node_id, embedding
FROM ag_catalog.node2vec('social_graph',
    node_label          => 'Person',
    edge_label          => 'knows',
    embedding_dimension => 64,
    return_factor       => 2.0,
    in_out_factor       => 0.5);

-- 大图降参配置:float32 + 低维 + 少 walk
SELECT node_id, embedding
FROM ag_catalog.node2vec('social_graph',
    embedding_dimension => 16,
    walks_per_node      => 2,
    walk_length         => 20,
    concurrency         => 16,
    configuration       => '{"embeddingPrecision": "float32",
                             "resultMode": "stats"}'::agtype);

-- 加权边:按边的 weight 属性影响 walk 采样概率
SELECT node_id, embedding
FROM ag_catalog.node2vec('social_graph',
    edge_label  => 'knows',
    weight_key  => 'strength',
    embedding_dimension => 64);

-- MUTATE 模式:将嵌入写入顶点属性
SELECT node_id AS stats
FROM ag_catalog.node2vec('social_graph',
    node_label          => 'Person',
    edge_label          => 'knows',
    embedding_dimension => 16,
    configuration       => '{"resultMode": "mutate"}'::agtype);