过滤后的节点相似度

本节介绍 Neo4j Graph Analytics for Snowflake 中的过滤节点相似度(Filtered Node Similarity)算法。该算法是节点相似度(Node Similarity)算法的扩展,支持对源节点、目标节点或两者同时进行过滤。

介绍

过滤节点相似度算法是 节点相似度 算法的扩展。它增加了对源节点、目标节点或两者进行过滤的支持。

节点过滤

节点过滤器缩小了算法产生结果的节点空间。考虑两个相似度结果:A = (alice)-[:SIMILAR_TO]→(bob)B = (bob)-[:SIMILAR_TO]→(alice)。如果 (alice) 节点匹配源节点过滤器且 (bob) 节点匹配目标节点过滤器,则会产生结果 A。如果 (alice) 节点不匹配目标节点过滤器,或者 (bob) 节点不匹配源节点过滤器,则不会产生结果 B

配置节点过滤器

有关节点相似度的标准配置,请参见 节点相似度语法

源节点过滤器通过 sourceNodeFilter 配置参数指定。目标节点过滤器通过 targetNodeFilter 配置参数指定。这两个参数都不是强制性的。

节点过滤器参数可接受以下内容之一:

表 1. sourceNodeFiltertargetNodeFilter 的语法

节点 ID 列表

sourceNodeFilter: ['Alice', 'Bob', 'Carol'] 并指定 sourceNodeTable: 'Person'

单个节点标签

sourceNodeFilter: 'Person'

语法

本节涵盖执行过滤节点相似度算法所使用的语法。

运行过滤节点相似度。
CALL Neo4j_Graph_Analytics.graph.node_similarity_filtered(
  'CPU_X64_XS',                    (1)
  {
    ['defaultTablePrefix': '...',] (2)
    'project': {...},              (3)
    'compute': {...},              (4)
    'write':   {...}               (5)
  }
);
1 计算池选择器。
2 表引用的可选前缀。
3 项目配置。
4 计算配置。
5 写入配置。
表 2. 参数
名称 类型 默认 可选 描述

computePoolSelector

字符串

不适用

用于运行过滤节点相似度作业的计算池选择器。

配置

Map

{}

用于图项目、算法计算和结果回写的配置。

配置映射由以下三个条目组成。

有关以下项目配置的更多详细信息,请参阅 项目文档
表 3. 项目配置
名称 类型

nodeTables

节点表列表。

relationshipTables

关系类型到关系表的映射。

表 4. 计算配置
名称 类型 默认 可选 描述

resultProperty

字符串

'similarity'

将回写到 Snowflake 数据库的关系属性。

resultRelationshipType

字符串

'SIMILAR_TO'

用于回写到 Snowflake 数据库的关系类型。

similarityCutoff

浮点数

1e-42

结果中显示相似度得分的下限。值必须介于 0 和 1 之间。

degreeCutoff

整数

1

节点被纳入比较所需满足的节点度数的包含性下限。该值不能低于 1。

upperDegreeCutoff

整数

2147483647

节点被纳入比较所需满足的节点度数的包含性上限。该值不能低于 1。

topK

整数

10

每个节点的得分数量上限。返回 K 个最大的结果。此值不能低于 1。

bottomK

整数

10

每个节点的得分数量上限。返回 K 个最小的结果。此值不能低于 1。

topN

整数

0

计算出的得分的全局总数上限。返回 N 个最大的结果。此值不能为负数,值为 0 表示没有全局上限。

bottomN

整数

0

计算出的得分的全局总数上限。返回 N 个最小的结果。此值不能为负数,值为 0 表示没有全局上限。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

similarityMetric

字符串

JACCARD

用于计算相似度的指标。可以是 JACCARDOVERLAPCOSINE

useComponents

布尔值或字符串

false

如果启用,过滤节点相似度将使用组件来提高计算性能,跳过不同组件中节点之间的比较。设置为 false(默认值):算法不使用组件,而是跨整个图计算相似度。设置为 true:算法使用组件,并在计算相似度之前先计算这些组件。设置为 String:使用存储在图中的预计算组件,String 是表示组件的节点属性键。

sourceNodeFilter

字符串或列表

null

源节点过滤器。可以是单个节点标签、节点标签列表、单个节点 ID 或节点 ID 列表。

sourceNodeTable

字符串

null

用于映射源节点标识符的表。

targetNodeFilter

字符串或列表

null

目标节点过滤器。可以是单个节点标签、节点标签列表、单个节点 ID 或节点 ID 列表。

targetNodeTable

字符串

null

用于映射目标节点标识符的表。

有关以下写入配置的更多详细信息,请参阅 写入文档
表 5. 写入配置
名称 类型 默认 可选 描述

sourceLabel

字符串

不适用

内存图中待回写关系起始节点的节点标签。

targetLabel

字符串

不适用

内存图中待回写关系结束节点的节点标签。

outputTable

字符串

不适用

关系写入的 Snowflake 数据库表。

关系类型 (relationshipType)

字符串

'SIMILAR_TO'

将回写到 Snowflake 数据库的关系类型。

relationshipProperty

字符串

'similarity'

将回写到 Snowflake 数据库的关系属性。

示例

在本节中,我们将展示在具体图上运行过滤节点相似度算法的示例。目的是说明结果的样子,并提供在实际场景中如何使用该算法的指南。我们将在一个包含少量节点、以特定模式连接的知识图谱上进行此操作。示例图如下所示:

Visualization of the example graph
以下 SQL 语句将在 Snowflake 数据库中创建示例图表:
CREATE OR REPLACE TABLE EXAMPLE_DB.DATA_SCHEMA.PERSONS (NODEID VARCHAR);
INSERT INTO EXAMPLE_DB.DATA_SCHEMA.PERSONS VALUES
  ('Alice'),
  ('Bob'),
  ('Carol'),
  ('Dave'),
  ('Eve');

CREATE OR REPLACE TABLE EXAMPLE_DB.DATA_SCHEMA.INSTRUMENTS (NODEID VARCHAR);
INSERT INTO EXAMPLE_DB.DATA_SCHEMA.INSTRUMENTS VALUES
  ('Guitar'),
  ('Synthesizer'),
  ('Bongos'),
  ('Trumpet');

CREATE OR REPLACE TABLE EXAMPLE_DB.DATA_SCHEMA.LIKES (SOURCENODEID VARCHAR, TARGETNODEID VARCHAR, WEIGHT FLOAT);
INSERT INTO EXAMPLE_DB.DATA_SCHEMA.LIKES VALUES
  ('Alice', 'Guitar',      1.0),
  ('Alice', 'Synthesizer', 1.0),
  ('Alice', 'Bongos',      0.5),
  ('Bob',   'Guitar',      1.0),
  ('Bob',   'Synthesizer', 1.0),
  ('Carol', 'Bongos',      1.0),
  ('Dave',  'Guitar',      1.0),
  ('Dave',  'Trumpet',     1.5),
  ('Dave',  'Bongos',      1.0);

这个二分图有两个节点集:人 (Person) 节点和乐器 (Instrument) 节点。这两个节点集通过 LIKES 关系连接。每条关系都始于一个 Person 节点,并终止于一个 Instrument 节点。

在此示例中,我们希望使用过滤节点相似度算法根据人们喜欢的乐器来比较他们。

过滤节点相似度算法仅计算度数至少为 1 的节点的相似度。在示例图中,Eve 节点不会与其他 Person 节点进行比较。

在以下示例中,我们将演示如何在具有各种过滤配置的图上使用过滤节点相似度算法。

运行作业

运行过滤节点相似度作业包括三个步骤:投影(Project)、计算(Compute)和写入(Write)。

要运行查询,需要为应用程序、您的消费者角色和您的环境设置必要的权限。请参阅 入门 页面以了解更多信息。

我们还假设应用程序名称为默认的 Neo4j_Graph_Analytics。如果您在安装过程中选择了不同的应用程序名称,请将其替换为该名称。

以下内容将运行带有源过滤器和目标过滤器的过滤节点相似度作业:
CALL Neo4j_Graph_Analytics.graph.node_similarity_filtered('CPU_X64_XS', {
    'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
    'project': {
        'nodeTables': ['PERSONS', 'INSTRUMENTS'],
        'relationshipTables': {
          'LIKES': {
            'sourceTable': 'PERSONS',
            'targetTable': 'INSTRUMENTS'
          }
        }
    },
    'compute': {
        'sourceNodeFilter': 'PERSONS',
        'targetNodeFilter': 'PERSONS'
    },
    'write': [{
        'outputTable': 'PERSONS_SIMILARITY',
        'sourceLabel': 'PERSONS',
        'targetLabel': 'PERSONS',
        'relationshipType': 'SIMILAR_TO',
        'relationshipProperty': 'similarity'
    }]
});
表 6. 结果
JOB_ID JOB_STATUS JOB_START JOB_END JOB_RESULT

job_36fa8f572b8b412fabb7d9343ed038f8

SUCCESS

2025-06-25 13:30:03.460

2025-06-25 13:30:10.288

{
  "node_similarity_filtered_1": {
    "computeMillis": 43,
    "configuration": {
      "bottomK": 10,
      "bottomN": 0,
      "concurrency": 2,
      "degreeCutoff": 1,
      "nodeLabels": ["*"],
      "relationshipTypes": ["*"],
      "resultProperty": "similarity",
      "resultRelationshipType": "SIMILAR_TO",
      "similarityCutoff": 1.000000000000000e-42,
      "similarityMetric": "JACCARD",
      "sourceNodeFilter": "NodeFilter[label=PERSONS]",
      "targetNodeFilter": "NodeFilter[label=PERSONS]",
      "topK": 10,
      "topN": 0,
      "upperDegreeCutoff": 2147483647,
      "useComponents": true
    },
    "nodesCompared": 4,
    "similarityDistribution": {
      "max": 0.6666679382324218,
      "mean": 0.41666641235351565,
      "min": 0.25,
      "p1": 0.25,
      "p10": 0.25,
      "p100": 0.6666660308837891,
      "p25": 0.3333320617675781,
      "p5": 0.25,
      "p50": 0.3333320617675781,
      "p75": 0.5000019073486328,
      "p90": 0.6666660308837891,
      "p95": 0.6666660308837891,
      "p99": 0.6666660308837891,
      "stdDev": 0.14907148283512542
    }
  },
  "project_1": {
    "graphName": "snowgraph",
    "nodeCount": 9,
    "nodeLabels": ...,
    "nodeMillis": 402,
    "relationshipCount": 9,
    "relationshipMillis": 531,
    "relationshipTypes": ...,
    "totalMillis": 933
  },
  "write_relationship_type_1": {
    "outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
    "relationshipProperty": "similarity",
    "relationshipType": "SIMILAR_TO",
    "rowsWritten": 10,
    "writeMillis": 2738
  }
}

返回的结果包含有关作业执行和结果分布的信息。此外,为已比较的节点对计算出的每个相似度分数都已写回 Snowflake 数据库。我们可以像这样查询它:

SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SIMILARITY DESC;

这显示了存储在数据库中的计算结果

表 7. 结果
SOURCENODEID TARGETNODEID SIMILARITY

Alice

Bob

0.6666666666666666

Bob

Alice

0.6666666666666666

Alice

Dave

0.5

Dave

Alice

0.5

Alice

Carol

0.3333333333333333

Carol

Alice

0.3333333333333333

Carol

Dave

0.3333333333333333

Dave

Carol

0.3333333333333333

Bob

Dave

0.25

Dave

Bob

0.25

我们对过程配置参数使用默认值。TopK 设置为 10,topN 设置为 0。因此,结果集包含每个节点的前 10 个相似度分数。

如果我们想改为比较乐器之间的相似性,我们将使用 REVERSE 方向来投影 LIKES 关系类型。这将返回乐器对的相似性,而不会计算人与人之间的任何相似性。

仅源过滤器

您可以仅对源节点应用过滤,允许考虑所有目标节点:

以下内容将运行仅带有源过滤的过滤节点相似度作业:
CALL Neo4j_Graph_Analytics.graph.node_similarity_filtered('CPU_X64_XS', {
    'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
    'project': {
        'nodeTables': ['PERSONS', 'INSTRUMENTS'],
        'relationshipTables': {
          'LIKES': {
            'sourceTable': 'PERSONS',
            'targetTable': 'INSTRUMENTS'
          }
        }
    },
    'compute': {
        'sourceNodeFilter': ['Alice', 'Bob'],
        'sourceNodeTable': 'PERSONS'
    },
    'write': [{
        'outputTable': 'PERSONS_SIMILARITY_NAMES',
        'sourceLabel': 'PERSONS',
        'targetLabel': 'PERSONS',
        'relationshipType': 'SIMILAR_TO',
        'relationshipProperty': 'similarity'
    }]
});
表 8. 结果
JOB_ID JOB_STATUS JOB_START JOB_END JOB_RESULT

job_c87ccfc6c46742548940fff74eeeeea6

SUCCESS

2025-06-25 13:47:42.029

2025-06-25 13:47:47.708

 {
  "node_similarity_filtered_1": {
    "computeMillis": 77,
    "configuration": {
      "bottomK": 10,
      "bottomN": 0,
      "concurrency": 2,
      "degreeCutoff": 1,
      "nodeLabels": ["*"],
      "relationshipTypes": ["*"],
      "resultProperty": "similarity",
      "resultRelationshipType": "SIMILAR_TO",
      "similarityCutoff": 1.000000000000000e-42,
      "similarityMetric": "JACCARD",
      "sourceNodeFilter": "NodeFilter[4, 5]",
      "sourceNodeTable": {},
      "targetNodeFilter": "NodeFilter[NoOp]",
      "topK": 10,
      "topN": 0,
      "upperDegreeCutoff": 2147483647,
      "useComponents": false
    },
    "nodesCompared": 2,
    "similarityDistribution": {
      "max": 0.6666679382324218,
      "mean": 0.4833332061767578,
      "min": 0.25,
      "p1": 0.25,
      "p10": 0.25,
      "p100": 0.6666660308837891,
      "p25": 0.3333320617675781,
      "p5": 0.25,
      "p50": 0.5000019073486328,
      "p75": 0.6666660308837891,
      "p90": 0.6666660308837891,
      "p95": 0.6666660308837891,
      "p99": 0.6666660308837891,
      "stdDev": 0.16996730465455073
    }
  },
  "project_1": {
    "graphName": "snowgraph",
    "nodeCount": 9,
    "nodeLabels": ...,
    "nodeMillis": 236,
    "relationshipCount": 9,
    "relationshipMillis": 342,
    "relationshipTypes": ...,
    "totalMillis": 578
  },
  "write_relationship_type_1": {
    "outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY_NAMES",
    "relationshipProperty": "similarity",
    "relationshipType": "SIMILAR_TO",
    "rowsWritten": 5,
    "writeMillis": 3438
  }
}
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY_NAMES ORDER BY SIMILARITY DESC;
表 9. 结果
SOURCENODEID TARGETNODEID SIMILARITY

Alice

Bob

0.6666666666666666

Bob

Alice

0.6666666666666666

Alice

Dave

0.5

Alice

Carol

0.3333333333333333

Bob

Dave

0.25

在这种情况下,仅 Alice 和 Bob 被用作源节点,但它们可以与所有 PERSONS 目标节点(包括 Dave 和 Carol)进行比较。

加权相似度计算在应用节点过滤器的同时考虑了关系权重,根据节点间关系的强度提供了更细致的相似度分数。