过滤后的节点相似度
本节介绍 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 配置参数指定。这两个参数都不是强制性的。
节点过滤器参数可接受以下内容之一:
节点 ID 列表 |
|
单个节点标签 |
|
语法
本节涵盖执行过滤节点相似度算法所使用的语法。
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 | 写入配置。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
computePoolSelector |
字符串 |
|
否 |
用于运行过滤节点相似度作业的计算池选择器。 |
配置 |
Map |
|
否 |
用于图项目、算法计算和结果回写的配置。 |
配置映射由以下三个条目组成。
| 有关以下项目配置的更多详细信息,请参阅 项目文档。 |
| 名称 | 类型 |
|---|---|
nodeTables |
节点表列表。 |
relationshipTables |
关系类型到关系表的映射。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
resultProperty |
字符串 |
|
是 |
将回写到 Snowflake 数据库的关系属性。 |
resultRelationshipType |
字符串 |
|
是 |
用于回写到 Snowflake 数据库的关系类型。 |
similarityCutoff |
浮点数 |
|
是 |
结果中显示相似度得分的下限。值必须介于 0 和 1 之间。 |
degreeCutoff |
整数 |
|
是 |
节点被纳入比较所需满足的节点度数的包含性下限。该值不能低于 1。 |
upperDegreeCutoff |
整数 |
|
是 |
节点被纳入比较所需满足的节点度数的包含性上限。该值不能低于 1。 |
topK |
整数 |
|
是 |
每个节点的得分数量上限。返回 K 个最大的结果。此值不能低于 1。 |
bottomK |
整数 |
|
是 |
每个节点的得分数量上限。返回 K 个最小的结果。此值不能低于 1。 |
topN |
整数 |
|
是 |
计算出的得分的全局总数上限。返回 N 个最大的结果。此值不能为负数,值为 0 表示没有全局上限。 |
bottomN |
整数 |
|
是 |
计算出的得分的全局总数上限。返回 N 个最小的结果。此值不能为负数,值为 0 表示没有全局上限。 |
relationshipWeightProperty |
字符串 |
|
是 |
用作权重的关系属性名称。如果未指定,算法将作为无权重运行。 |
similarityMetric |
字符串 |
|
是 |
用于计算相似度的指标。可以是 |
useComponents |
布尔值或字符串 |
|
是 |
如果启用,过滤节点相似度将使用组件来提高计算性能,跳过不同组件中节点之间的比较。设置为 |
sourceNodeFilter |
字符串或列表 |
|
是 |
源节点过滤器。可以是单个节点标签、节点标签列表、单个节点 ID 或节点 ID 列表。 |
sourceNodeTable |
字符串 |
|
是 |
用于映射源节点标识符的表。 |
targetNodeFilter |
字符串或列表 |
|
是 |
目标节点过滤器。可以是单个节点标签、节点标签列表、单个节点 ID 或节点 ID 列表。 |
targetNodeTable |
字符串 |
|
是 |
用于映射目标节点标识符的表。 |
| 有关以下写入配置的更多详细信息,请参阅 写入文档。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
sourceLabel |
字符串 |
|
否 |
内存图中待回写关系起始节点的节点标签。 |
targetLabel |
字符串 |
|
否 |
内存图中待回写关系结束节点的节点标签。 |
outputTable |
字符串 |
|
否 |
关系写入的 Snowflake 数据库表。 |
关系类型 (relationshipType) |
字符串 |
|
是 |
将回写到 Snowflake 数据库的关系类型。 |
relationshipProperty |
字符串 |
|
是 |
将回写到 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'
}]
});
| 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;
这显示了存储在数据库中的计算结果
| 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 个相似度分数。
|
如果我们想改为比较乐器之间的相似性,我们将使用 |
仅源过滤器
您可以仅对源节点应用过滤,允许考虑所有目标节点:
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'
}]
});
| 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;
| 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)进行比较。
加权相似度计算在应用节点过滤器的同时考虑了关系权重,根据节点间关系的强度提供了更细致的相似度分数。