节点相似度 (Node Similarity)
本节介绍 Neo4j Graph Analytics for Snowflake 中的节点相似度(Node Similarity)算法。该算法基于 Jaccard 和 Overlap(重叠)相似度指标。
简介
节点相似度算法根据节点所连接的对象来比较一组节点。如果两个节点共享许多相同的邻居,则认为它们是相似的。节点相似度基于 Jaccard 指标(也称为 Jaccard 相似度得分)、Overlap 系数(也称为 Szymkiewicz–Simpson 系数)以及余弦相似度(Cosine Similarity)得分来计算成对相似度。前两者最常用于无权集合,而余弦相似度则常用于加权输入。
给定两个集合 A 和 B,Jaccard 相似度使用以下公式计算
Overlap 系数使用以下公式计算
加权情况下的公式可以在下方的加权示例中找到。
余弦相似度得分使用以下公式计算,其中当 A 和 B 为无权时,条目被隐含地赋予权重 1
该算法的输入是一个包含两个不相交节点集的二分连通图。每条关系都从第一个节点集中的一个节点开始,并指向第二个节点集中的一个节点。
节点相似度算法将每个具有出站关系的节点与其它此类节点进行比较。对于每个节点 n,我们收集该节点的出站邻域 N(n),即所有满足存在从 n 到 m 的关系的节点 m。对于每一对 n 和 m,算法会计算该对的相似度,结果等于所选相似度指标对 N(n) 和 N(m) 计算得出的值。
节点相似度的时间复杂度为 O(n3),空间复杂度为 O(n2)。我们以 O(n2) 的时间和空间计算并存储邻居集,然后以 O(n3) 的时间计算成对相似度得分。
为了限制内存使用,您可以指定每个节点输出结果数量的明确限制,即 'topK' 参数。它可以设置为除 0 以外的任何值。当然,您会在整体计算中损失精度,但运行时间不受影响——我们仍然必须在可能丢弃结果之前计算出结果。
算法的输出是第一个节点集中各对节点之间的新关系。相似度得分通过关系属性来表示。
有关此算法的更多信息,请参阅
语法
本节涵盖了执行节点相似度算法所使用的语法。
CALL Neo4j_Graph_Analytics.graph.node_similarity(
'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 |
布尔值或字符串 |
|
是 |
如果启用,节点相似度将使用组件来提高计算性能,跳过不同组件中节点之间的比较。设置为 |
| 有关以下写入配置的更多详细信息,请参阅 写入文档。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
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('CPU_X64_XS', {
'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
'project': {
'nodeTables': ['PERSONS', 'INSTRUMENTS'],
'relationshipTables': {
'LIKES': {
'sourceTable': 'PERSONS',
'targetTable': 'INSTRUMENTS'
}
}
},
'compute': {
'resultProperty': 'score',
'resultRelationshipType': 'SIMILAR'
},
'write': [{
'outputTable': 'PERSONS_SIMILARITY',
'sourceLabel': 'PERSONS',
'targetLabel': 'PERSONS',
'relationshipType': 'SIMILAR',
'relationshipProperty': 'score'
}]
});
| 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_1": {
"computeMillis": 60,
"configuration": {
"bottomK": 10,
"bottomN": 0,
"concurrency": 2,
"degreeCutoff": 1,
"nodeLabels": ["*"],
"relationshipTypes": ["*"],
"resultProperty": "score",
"resultRelationshipType": "SIMILAR",
"similarityCutoff": 1.000000000000000e-42,
"similarityMetric": "JACCARD",
"topK": 10,
"topN": 0,
"upperDegreeCutoff": 2147483647,
"useComponents": false
},
"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": 872,
"relationshipCount": 9,
"relationshipMillis": 469,
"relationshipTypes": ...,
"totalMillis": 1341
},
"write_relationship_type_1": {
"outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
"relationshipProperty": "score",
"relationshipType": "SIMILAR",
"rowsWritten": 10,
"writeMillis": 1917
}
} |
返回的结果包含有关作业执行和结果分布的信息。此外,为已比较节点对计算出的每个相似度得分已写回 Snowflake 数据库。我们可以这样查询它
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SCORE DESC;
这显示了存储在数据库中的计算结果
| SOURCENODEID | TARGETNODEID | SCORE |
|---|---|---|
Alice |
Bob |
0.6666666667 |
Bob |
Alice |
0.6666666667 |
Alice |
Dave |
0.5 |
Dave |
Alice |
0.5 |
Alice |
Carol |
0.3333333333 |
Carol |
Alice |
0.3333333333 |
Carol |
Dave |
0.3333333333 |
Dave |
Carol |
0.3333333333 |
Bob |
Dave |
0.25 |
Dave |
Bob |
0.25 |
我们为过程配置参数使用默认值。TopK 设置为 10,topN 设置为 0。因此,结果集包含每个节点的前 10 个相似度得分。
|
如果我们想改为比较乐器之间的相似性,我们将使用 |
限制结果
可以对相似度结果应用四种限制。Top 将结果限制为最高的相似度得分。Bottom 将结果限制为最低的相似度得分。Top 和 bottom 限制都可以应用于整个结果集("N"),或者应用于每个节点的结果("K")。
|
必须始终存在一个 "K" 限制(bottomK 或 topK),它必须是一个正数。topK 和 bottomK 的默认值为 10。 |
| 总结果数 | 每个节点的结果数 | |
|---|---|---|
最高得分 |
topN |
topK |
最低得分 |
bottomN |
bottomK |
topK 和 bottomK
TopK 和 bottomK 是对每个节点计算得分数量的限制。对于 topK,返回每个节点得分最高的 K 个相似度得分。对于 bottomK,返回每个节点得分最低的 K 个相似度得分。TopK 和 bottomK 不能为 0,不能同时使用,默认值为 10。如果未指定两者中的任何一个,则使用 topK。
CALL Neo4j_Graph_Analytics.graph.node_similarity('CPU_X64_XS', {
'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
'project': {
'nodeTables': ['PERSONS', 'INSTRUMENTS'],
'relationshipTables': {
'LIKES': {
'sourceTable': 'PERSONS',
'targetTable': 'INSTRUMENTS'
}
}
},
'compute': {
'resultProperty': 'score',
'resultRelationshipType': 'SIMILAR',
'topK': 1
},
'write': [{
'outputTable': 'PERSONS_SIMILARITY',
'sourceLabel': 'PERSONS',
'targetLabel': 'PERSONS',
'relationshipType': 'SIMILAR',
'relationshipProperty': 'score'
}]
});
| 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_1": {
"computeMillis": 33,
"configuration": {
"bottomK": 10,
"bottomN": 0,
"concurrency": 2,
"degreeCutoff": 1,
"nodeLabels": ["*"],
"relationshipTypes": ["*"],
"resultProperty": "score",
"resultRelationshipType": "SIMILAR",
"similarityCutoff": 1.000000000000000e-42,
"similarityMetric": "JACCARD",
"topK": 1,
"topN": 0,
"upperDegreeCutoff": 2147483647,
"useComponents": false
},
"nodesCompared": 4,
"similarityDistribution": {
"max": 0.6666679382324218,
"mean": 0.5416665077209473,
"min": 0.3333320617675781,
"p1": 0.3333320617675781,
"p10": 0.3333320617675781,
"p100": 0.6666660308837891,
"p25": 0.3333320617675781,
"p5": 0.3333320617675781,
"p50": 0.5000019073486328,
"p75": 0.6666660308837891,
"p90": 0.6666660308837891,
"p95": 0.6666660308837891,
"p99": 0.6666660308837891,
"stdDev": 0.13819274752746397
}
},
"project_1": {
"graphName": "snowgraph",
"nodeCount": 9,
"nodeLabels": ...,
"nodeMillis": 218,
"relationshipCount": 9,
"relationshipMillis": 322,
"relationshipTypes": ...,
"totalMillis": 540
},
"write_relationship_type_1": {
"outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
"relationshipProperty": "score",
"relationshipType": "SIMILAR",
"rowsWritten": 4,
"writeMillis": 1958
}
} |
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SCORE DESC;
| SOURCENODEID | TARGETNODEID | SCORE |
|---|---|---|
Alice |
Bob |
0.6666666667 |
Bob |
Alice |
0.6666666667 |
Dave |
Alice |
0.5 |
Carol |
Alice |
0.3333333333 |
以下是如何使用 bottomK 的示例
CALL Neo4j_Graph_Analytics.graph.node_similarity('CPU_X64_XS', {
'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
'project': {
'nodeTables': ['PERSONS', 'INSTRUMENTS'],
'relationshipTables': {
'LIKES': {
'sourceTable': 'PERSONS',
'targetTable': 'INSTRUMENTS'
}
}
},
'compute': {
'resultProperty': 'score',
'resultRelationshipType': 'SIMILAR',
'bottomK': 1
},
'write': [{
'outputTable': 'PERSONS_SIMILARITY',
'sourceLabel': 'PERSONS',
'targetLabel': 'PERSONS',
'relationshipType': 'SIMILAR',
'relationshipProperty': 'score'
}]
});
| JOB_ID | JOB_STATUS | JOB_START | JOB_END | JOB_RESULT |
|---|---|---|---|---|
job_2fdc12517bc54905906e2f2eb396d00b |
SUCCESS |
2025-06-25 14:14:47.657 |
2025-06-25 14:14:53.313 |
{
"node_similarity_1": {
"computeMillis": 25,
"configuration": {
"bottomK": 1,
"bottomN": 0,
"concurrency": 2,
"degreeCutoff": 1,
"nodeLabels": ["*"],
"relationshipTypes": ["*"],
"resultProperty": "score",
"resultRelationshipType": "SIMILAR",
"similarityCutoff": 1.000000000000000e-42,
"similarityMetric": "JACCARD",
"topK": 10,
"topN": 0,
"upperDegreeCutoff": 2147483647,
"useComponents": false
},
"nodesCompared": 4,
"similarityDistribution": {
"max": 0.3333339691162109,
"mean": 0.29166603088378906,
"min": 0.25,
"p1": 0.25,
"p10": 0.25,
"p100": 0.3333320617675781,
"p25": 0.25,
"p5": 0.25,
"p50": 0.25,
"p75": 0.3333320617675781,
"p90": 0.3333320617675781,
"p95": 0.3333320617675781,
"p99": 0.3333320617675781,
"stdDev": 0.04166603088378906
}
},
"project_1": {
"graphName": "snowgraph",
"nodeCount": 9,
"nodeLabels": ...,
"nodeMillis": 188,
"relationshipCount": 9,
"relationshipMillis": 369,
"relationshipTypes": ...,
"totalMillis": 557
},
"write_relationship_type_1": {
"outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
"relationshipProperty": "score",
"relationshipType": "SIMILAR",
"rowsWritten": 4,
"writeMillis": 2105
}
} |
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SCORE DESC;
| SOURCENODEID | TARGETNODEID | SCORE |
|---|---|---|
Alice |
Carol |
0.3333333333 |
Carol |
Alice |
0.3333333333 |
Bob |
Dave |
0.25 |
Dave |
Bob |
0.25 |
topN 和 bottomN
TopN 和 bottomN 限制了所有节点上的相似度得分数量。这是对总结果集的限制,是对每个节点 topK 或 bottomK 限制的补充。对于 topN,返回 N 个最高的相似度得分。对于 bottomN,返回 N 个最低的相似度得分。值为 0 表示不施加全局限制,并返回 topK 或 bottomK 的所有结果。
CALL Neo4j_Graph_Analytics.graph.node_similarity('CPU_X64_XS', {
'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
'project': {
'nodeTables': ['PERSONS', 'INSTRUMENTS'],
'relationshipTables': {
'LIKES': {
'sourceTable': 'PERSONS',
'targetTable': 'INSTRUMENTS'
}
}
},
'compute': {
'resultProperty': 'score',
'resultRelationshipType': 'SIMILAR',
'topK': 1,
'topN': 3
},
'write': [{
'outputTable': 'PERSONS_SIMILARITY',
'sourceLabel': 'PERSONS',
'targetLabel': 'PERSONS',
'relationshipType': 'SIMILAR',
'relationshipProperty': 'score'
}]
});
| JOB_ID | JOB_STATUS | JOB_START | JOB_END | JOB_RESULT |
|---|---|---|---|---|
job_ab183c8a38e64d23936b61781cebe2e7 |
SUCCESS |
2025-06-26 07:15:15.951 |
2025-06-26 07:15:22.810 |
{
"node_similarity_1": {
"computeMillis": 45,
"configuration": {
"bottomK": 10,
"bottomN": 0,
"concurrency": 2,
"degreeCutoff": 1,
"nodeLabels": ["*"],
"relationshipTypes": ["*"],
"resultProperty": "score",
"resultRelationshipType": "SIMILAR",
"similarityCutoff": 1.000000000000000e-42,
"similarityMetric": "JACCARD",
"topK": 1,
"topN": 3,
"upperDegreeCutoff": 2147483647,
"useComponents": false
},
"nodesCompared": 4,
"similarityDistribution": {
"max": 0.6666679382324218,
"mean": 0.6111094156901041,
"min": 0.5,
"p1": 0.5,
"p10": 0.5,
"p100": 0.6666641235351562,
"p25": 0.5,
"p5": 0.5,
"p50": 0.6666641235351562,
"p75": 0.6666641235351562,
"p90": 0.6666641235351562,
"p95": 0.6666641235351562,
"p99": 0.6666641235351562,
"stdDev": 0.07856622128814764
}
},
"project_1": {
"graphName": "snowgraph",
"nodeCount": 9,
"nodeLabels": ...,
"nodeMillis": 914,
"relationshipCount": 9,
"relationshipMillis": 662,
"relationshipTypes": ...,
"totalMillis": 1576
},
"write_relationship_type_1": {
"outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
"relationshipProperty": "score",
"relationshipType": "SIMILAR",
"rowsWritten": 3,
"writeMillis": 2113
}
} |
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SCORE DESC;
| SOURCENODEID | TARGETNODEID | SCORE |
|---|---|---|
Alice |
Bob |
0.6666666667 |
Bob |
Alice |
0.6666666667 |
Dave |
Alice |
0.5 |
度数截断和相似度截断
可以通过两个名为 degreeCutoff 和 upperDegreeCutoff 的整数参数来调整节点相似度,以基于度数约束忽略某些节点。如果设置了 degreeCutoff,它会对度数施加下限,只有度数高于此值的节点才会被考虑在比较中,并跳过任何度数低于 degreeCutoff 的节点。如果设置了 upperDegreeCutoff,它会对节点度数施加上限,并跳过任何度数高于 upperDegreeCutoff 的节点。这两个参数也可以组合使用,以便只考虑度数落入特定区间的节点。
两个参数的最小值为 1。
CALL Neo4j_Graph_Analytics.graph.node_similarity('CPU_X64_XS', {
'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
'project': {
'nodeTables': ['PERSONS', 'INSTRUMENTS'],
'relationshipTables': {
'LIKES': {
'sourceTable': 'PERSONS',
'targetTable': 'INSTRUMENTS'
}
}
},
'compute': {
'resultProperty': 'score',
'resultRelationshipType': 'SIMILAR',
'degreeCutoff': 3
},
'write': [{
'outputTable': 'PERSONS_SIMILARITY',
'sourceLabel': 'PERSONS',
'targetLabel': 'PERSONS',
'relationshipType': 'SIMILAR',
'relationshipProperty': 'score'
}]
});
| JOB_ID | JOB_STATUS | JOB_START | JOB_END | JOB_RESULT |
|---|---|---|---|---|
job_3687173082d14993a228eab0663ff557 |
SUCCESS |
2025-06-26 08:14:43.945 |
2025-06-26 08:14:49.441 |
{
"node_similarity_1": {
"computeMillis": 23,
"configuration": {
"bottomK": 10,
"bottomN": 0,
"concurrency": 2,
"degreeCutoff": 3,
"nodeLabels": ["*"],
"relationshipTypes": ["*"],
"resultProperty": "score",
"resultRelationshipType": "SIMILAR",
"similarityCutoff": 1.000000000000000e-42,
"similarityMetric": "JACCARD",
"topK": 10,
"topN": 0,
"upperDegreeCutoff": 2147483647,
"useComponents": false
},
"nodesCompared": 2,
"similarityDistribution": {
"max": 0.5000038146972655,
"mean": 0.5,
"min": 0.5,
"p1": 0.5,
"p10": 0.5,
"p100": 0.5,
"p25": 0.5,
"p5": 0.5,
"p50": 0.5,
"p75": 0.5,
"p90": 0.5,
"p95": 0.5,
"p99": 0.5,
"stdDev": 0
}
},
"project_1": {
"graphName": "snowgraph",
"nodeCount": 9,
"nodeLabels": ...,
"nodeMillis": 227,
"relationshipCount": 9,
"relationshipMillis": 426,
"relationshipTypes": ...,
"totalMillis": 653
},
"write_relationship_type_1": {
"outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
"relationshipProperty": "score",
"relationshipType": "SIMILAR",
"rowsWritten": 2,
"writeMillis": 1931
}
} |
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SCORE DESC;
| SOURCENODEID | TARGETNODEID | SCORE |
|---|---|---|
Alice |
Dave |
0.5 |
Dave |
Alice |
0.5 |
相似度截断(Similarity cutoff)是结果中包含的相似度得分的下限。默认值非常小 (1E-42),用于排除相似度得分为 0 的结果。
|
将相似度截断设置为 0 可能会产生非常大的结果集,并增加运行时间和内存消耗。 |
CALL Neo4j_Graph_Analytics.graph.node_similarity('CPU_X64_XS', {
'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
'project': {
'nodeTables': ['PERSONS', 'INSTRUMENTS'],
'relationshipTables': {
'LIKES': {
'sourceTable': 'PERSONS',
'targetTable': 'INSTRUMENTS'
}
}
},
'compute': {
'resultProperty': 'score',
'resultRelationshipType': 'SIMILAR',
'similarityCutoff': 0.5
},
'write': [{
'outputTable': 'PERSONS_SIMILARITY',
'sourceLabel': 'PERSONS',
'targetLabel': 'PERSONS',
'relationshipType': 'SIMILAR',
'relationshipProperty': 'score'
}]
});
| JOB_ID | JOB_STATUS | JOB_START | JOB_END | JOB_RESULT |
|---|---|---|---|---|
job_5f6827d7e57949209a48a876875ab65b |
SUCCESS |
2025-06-26 09:45:59.862 |
2025-06-26 09:46:05.996 |
{
"node_similarity_1": {
"computeMillis": 28,
"configuration": {
"bottomK": 10,
"bottomN": 0,
"concurrency": 2,
"degreeCutoff": 1,
"nodeLabels": ["*"],
"relationshipTypes": ["*"],
"resultProperty": "score",
"resultRelationshipType": "SIMILAR",
"similarityCutoff": 0.5,
"similarityMetric": "JACCARD",
"topK": 10,
"topN": 0,
"upperDegreeCutoff": 2147483647,
"useComponents": false
},
"nodesCompared": 4,
"similarityDistribution": {
"max": 0.6666679382324218,
"mean": 0.5833320617675781,
"min": 0.5,
"p1": 0.5,
"p10": 0.5,
"p100": 0.6666641235351562,
"p25": 0.5,
"p5": 0.5,
"p50": 0.5,
"p75": 0.6666641235351562,
"p90": 0.6666641235351562,
"p95": 0.6666641235351562,
"p99": 0.6666641235351562,
"stdDev": 0.08333206176757812
}
},
"project_1": {
"graphName": "snowgraph",
"nodeCount": 9,
"nodeLabels": ...,
"nodeMillis": 340,
"relationshipCount": 9,
"relationshipMillis": 522,
"relationshipTypes": ...,
"totalMillis": 862
},
"write_relationship_type_1": {
"outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
"relationshipProperty": "score",
"relationshipType": "SIMILAR",
"rowsWritten": 4,
"writeMillis": 2245
}
} |
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SCORE DESC;
| SOURCENODEID | TARGETNODEID | SCORE |
|---|---|---|
Alice |
Bob |
0.6666666667 |
Bob |
Alice |
0.6666666667 |
Alice |
Dave |
0.5 |
Dave |
Alice |
0.5 |
加权相似度
关系属性可用于通过将其值作为衡量重要性的方式,来修改由特定关系诱导的相似度。默认情况下,加权节点相似度使用加权 Jaccard 相似度,公式如下
从形式上讲,给定两个节点及其加权邻居列表 A' 和 B',我们将列表扩展为 A 和 B,通过为任何非邻居设置权重 = 0,在它们的邻居并集 A' ∪ B' 上建立索引,然后应用加权 Jaccard 相似度。
它还支持加权 Overlap 相似度,公式如下
此外,正如简介中提到的,余弦相似度也可以用于加权情况。
|
加权相似度指标仅针对大于或等于 0 的值定义。 |
CALL Neo4j_Graph_Analytics.graph.node_similarity('CPU_X64_XS', {
'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
'project': {
'nodeTables': ['PERSONS', 'INSTRUMENTS'],
'relationshipTables': {
'LIKES': {
'sourceTable': 'PERSONS',
'targetTable': 'INSTRUMENTS'
}
}
},
'compute': {
'resultProperty': 'score',
'resultRelationshipType': 'SIMILAR',
'relationshipWeightProperty': 'WEIGHT',
'similarityCutoff': 0.3
},
'write': [{
'outputTable': 'PERSONS_SIMILARITY',
'sourceLabel': 'PERSONS',
'targetLabel': 'PERSONS',
'relationshipType': 'SIMILAR',
'relationshipProperty': 'score'
}]
});
| JOB_ID | JOB_STATUS | JOB_START | JOB_END | JOB_RESULT |
|---|---|---|---|---|
job_532fbaf2ca3345168509c103dab5a419 |
SUCCESS |
2025-07-02 08:18:07.452 |
2025-07-02 08:18:13.844 |
{
"node_similarity_1": {
"computeMillis": 25,
"configuration": {
"bottomK": 10,
"bottomN": 0,
"concurrency": 2,
"degreeCutoff": 1,
"nodeLabels": ["*"],
"relationshipTypes": ["*"],
"relationshipWeightProperty": "WEIGHT",
"resultProperty": "score",
"resultRelationshipType": "SIMILAR",
"similarityCutoff": 0.3,
"similarityMetric": "JACCARD",
"topK": 10,
"topN": 0,
"upperDegreeCutoff": 2147483647,
"useComponents": false
},
"nodesCompared": 4,
"similarityDistribution": {
"max": 0.8000030517578124,
"mean": 0.5666666030883789,
"min": 0.3333320617675781,
"p1": 0.3333320617675781,
"p10": 0.3333320617675781,
"p100": 0.8000011444091797,
"p25": 0.3333320617675781,
"p5": 0.3333320617675781,
"p50": 0.3333320617675781,
"p75": 0.8000011444091797,
"p90": 0.8000011444091797,
"p95": 0.8000011444091797,
"p99": 0.8000011444091797,
"stdDev": 0.23333454132080078
}
},
"project_1": {
"graphName": "snowgraph",
"nodeCount": 9,
"nodeLabels": ...,
"nodeMillis": 640,
"relationshipCount": 9,
"relationshipMillis": 719,
"relationshipTypes": ...,
"totalMillis": 1359
},
"write_relationship_type_1": {
"outputTable": "EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
"relationshipProperty": "score",
"relationshipType": "SIMILAR",
"rowsWritten": 4,
"writeMillis": 1973
}
} |
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SCORE DESC;
| SOURCENODEID | TARGETNODEID | SCORE |
|---|---|---|
Alice |
Bob |
0.8 |
Alice |
Dave |
0.3333333333 |
Bob |
Alice |
0.8 |
Dave |
Alice |
0.3333333333 |
可以看到,与该算法的非加权版本相比,Alice 和 Dave 之间的相似度降低了(从 0.5 降至 0.33)。
Alice 喜欢吉他、合成器和邦戈鼓,强度为 (1, 1, 0.5)。Dave 喜欢吉他、邦戈鼓和喇叭,强度为 (1, 1, 1.5)。因此,取 Alice 和 Dave 的邻居,我们得到 Alice 的强度列表为 A = (1, 1, 0.5, 0),Dave 的为 B = (1, 0, 1, 1.5),按 吉他、合成器、邦戈鼓、喇叭 索引。
因此,Alice 和 Dave 的加权(Jaccard)节点相似度为
类似地,Alice 和 Bob 之间的相似度增加了(从 0.66 增至 0.8),因为缺失的喜欢的乐器对相似度得分的影响较小。