Skip to content
This repository was archived by the owner on Apr 22, 2020. It is now read-only.

Commit c7b881a

Browse files
authored
3.4 nan skip value (#795)
* default skipValue to NaN * cosine docs with skipValue * euclidean docs with skipValue * pearson docs with skipValue * david feedback
1 parent 02d854f commit c7b881a

File tree

10 files changed

+302
-145
lines changed

10 files changed

+302
-145
lines changed

algo/src/main/java/org/neo4j/graphalgo/similarity/CosineProc.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public Stream<SimilarityResult> cosineStream(
3838
@Name(value = "data", defaultValue = "null") Object rawData,
3939
@Name(value = "config", defaultValue = "{}") Map<String, Object> config) throws Exception {
4040
ProcedureConfiguration configuration = ProcedureConfiguration.create(config);
41-
Double skipValue = configuration.get("skipValue", null);
41+
Double skipValue = configuration.get("skipValue", Double.NaN);
4242

4343
WeightedInput[] inputs = prepareWeights(rawData, configuration, skipValue);
4444

@@ -62,7 +62,7 @@ public Stream<SimilaritySummaryResult> cosine(
6262
@Name(value = "config", defaultValue = "{}") Map<String, Object> config) throws Exception {
6363

6464
ProcedureConfiguration configuration = ProcedureConfiguration.create(config);
65-
Double skipValue = configuration.get("skipValue", null);
65+
Double skipValue = configuration.get("skipValue", Double.NaN);
6666

6767
WeightedInput[] inputs = prepareWeights(rawData, configuration, skipValue);
6868

algo/src/main/java/org/neo4j/graphalgo/similarity/EuclideanProc.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public Stream<SimilarityResult> euclideanStream(
3838
@Name(value = "data", defaultValue = "null") Object rawData,
3939
@Name(value = "config", defaultValue = "{}") Map<String, Object> config) throws Exception {
4040
ProcedureConfiguration configuration = ProcedureConfiguration.create(config);
41-
Double skipValue = configuration.get("skipValue", null);
41+
Double skipValue = readSkipValue(configuration);
4242
SimilarityComputer<WeightedInput> computer = similarityComputer(skipValue);
4343

4444
WeightedInput[] inputs = prepareWeights(rawData, configuration, skipValue);
@@ -54,14 +54,15 @@ public Stream<SimilarityResult> euclideanStream(
5454
return generateWeightedStream(configuration, inputs, similarityCutoff, topN, topK, computer);
5555
}
5656

57+
5758
@Procedure(name = "algo.similarity.euclidean", mode = Mode.WRITE)
5859
@Description("CALL algo.similarity.euclidean([{item:id, weights:[weights]}], {similarityCutoff:-1,degreeCutoff:0}) " +
5960
"YIELD p50, p75, p90, p99, p999, p100 - computes euclidean similarities")
6061
public Stream<SimilaritySummaryResult> euclidean(
6162
@Name(value = "data", defaultValue = "null") Object rawData,
6263
@Name(value = "config", defaultValue = "{}") Map<String, Object> config) throws Exception {
6364
ProcedureConfiguration configuration = ProcedureConfiguration.create(config);
64-
Double skipValue = configuration.get("skipValue", null);
65+
Double skipValue = readSkipValue(configuration);
6566
SimilarityComputer<WeightedInput> computer = similarityComputer(skipValue);
6667

6768
WeightedInput[] inputs = prepareWeights(rawData, configuration, skipValue);

algo/src/main/java/org/neo4j/graphalgo/similarity/PearsonProc.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public Stream<SimilarityResult> pearsonStream(
3838
@Name(value = "data", defaultValue = "null") Object rawData,
3939
@Name(value = "config", defaultValue = "{}") Map<String, Object> config) throws Exception {
4040
ProcedureConfiguration configuration = ProcedureConfiguration.create(config);
41-
Double skipValue = configuration.get("skipValue", null);
41+
Double skipValue = readSkipValue(configuration);
4242

4343
SimilarityComputer<WeightedInput> computer = similarityComputer(skipValue);
4444

@@ -62,7 +62,7 @@ public Stream<SimilaritySummaryResult> pearson(
6262
@Name(value = "data", defaultValue = "null") Object rawData,
6363
@Name(value = "config", defaultValue = "{}") Map<String, Object> config) throws Exception {
6464
ProcedureConfiguration configuration = ProcedureConfiguration.create(config);
65-
Double skipValue = configuration.get("skipValue", null);
65+
Double skipValue = readSkipValue(configuration);
6666
SimilarityComputer<WeightedInput> computer = similarityComputer(skipValue);
6767

6868
WeightedInput[] inputs = prepareWeights(rawData, configuration, skipValue);

algo/src/main/java/org/neo4j/graphalgo/similarity/SimilarityProc.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,17 +224,17 @@ CategoricalInput[] prepareCategories(List<Map<String, Object>> data, long degree
224224

225225
WeightedInput[] prepareWeights(Object rawData, ProcedureConfiguration configuration, Double skipValue) throws Exception {
226226
if (ProcedureConstants.CYPHER_QUERY.equals(configuration.getGraphName("dense"))) {
227-
if (skipValue == null) {
228-
throw new IllegalArgumentException("Must specify 'skipValue' when using {graph: 'cypher'}");
229-
}
230-
231227
return prepareSparseWeights(api, (String) rawData, skipValue, configuration);
232228
} else {
233229
List<Map<String, Object>> data = (List<Map<String, Object>>) rawData;
234230
return preparseDenseWeights(data, getDegreeCutoff(configuration), skipValue);
235231
}
236232
}
237233

234+
Double readSkipValue(ProcedureConfiguration configuration) {
235+
return configuration.get("skipValue", Double.NaN);
236+
}
237+
238238
WeightedInput[] preparseDenseWeights(List<Map<String, Object>> data, long degreeCutoff, Double skipValue) {
239239
WeightedInput[] inputs = new WeightedInput[data.size()];
240240
int idx = 0;

doc/asciidoc/scripts/similarity-cosine.cypher

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ MERGE (italian:Cuisine {name:'Italian'})
99
MERGE (indian:Cuisine {name:'Indian'})
1010
MERGE (lebanese:Cuisine {name:'Lebanese'})
1111
MERGE (portuguese:Cuisine {name:'Portuguese'})
12+
MERGE (british:Cuisine {name:'British'})
13+
MERGE (mauritian:Cuisine {name:'Mauritian'})
1214

1315
MERGE (zhen:Person {name: "Zhen"})
1416
MERGE (praveena:Person {name: "Praveena"})
@@ -18,27 +20,33 @@ MERGE (karin:Person {name: "Karin"})
1820

1921
MERGE (praveena)-[:LIKES {score: 9}]->(indian)
2022
MERGE (praveena)-[:LIKES {score: 7}]->(portuguese)
23+
MERGE (praveena)-[:LIKES {score: 8}]->(british)
24+
MERGE (praveena)-[:LIKES {score: 1}]->(mauritian)
2125

2226
MERGE (zhen)-[:LIKES {score: 10}]->(french)
2327
MERGE (zhen)-[:LIKES {score: 6}]->(indian)
28+
MERGE (zhen)-[:LIKES {score: 2}]->(british)
2429

2530
MERGE (michael)-[:LIKES {score: 8}]->(french)
2631
MERGE (michael)-[:LIKES {score: 7}]->(italian)
2732
MERGE (michael)-[:LIKES {score: 9}]->(indian)
33+
MERGE (michael)-[:LIKES {score: 3}]->(portuguese)
2834

2935
MERGE (arya)-[:LIKES {score: 10}]->(lebanese)
3036
MERGE (arya)-[:LIKES {score: 10}]->(italian)
3137
MERGE (arya)-[:LIKES {score: 7}]->(portuguese)
38+
MERGE (arya)-[:LIKES {score: 9}]->(mauritian)
3239

3340
MERGE (karin)-[:LIKES {score: 9}]->(lebanese)
3441
MERGE (karin)-[:LIKES {score: 7}]->(italian)
42+
MERGE (karin)-[:LIKES {score: 10}]->(portuguese)
3543

3644
// end::create-sample-graph[]
3745

3846
// tag::stream[]
3947
MATCH (p:Person), (c:Cuisine)
4048
OPTIONAL MATCH (p)-[likes:LIKES]->(c)
41-
WITH {item:id(p), weights: collect(coalesce(likes.score, 0))} as userData
49+
WITH {item:id(p), weights: collect(coalesce(likes.score, algo.NaN()))} as userData
4250
WITH collect(userData) as data
4351
CALL algo.similarity.cosine.stream(data)
4452
YIELD item1, item2, count1, count2, similarity
@@ -49,7 +57,7 @@ ORDER BY similarity DESC
4957
// tag::stream-similarity-cutoff[]
5058
MATCH (p:Person), (c:Cuisine)
5159
OPTIONAL MATCH (p)-[likes:LIKES]->(c)
52-
WITH {item:id(p), weights: collect(coalesce(likes.score, 0))} as userData
60+
WITH {item:id(p), weights: collect(coalesce(likes.score, algo.NaN()))} as userData
5361
WITH collect(userData) as data
5462
CALL algo.similarity.cosine.stream(data, {similarityCutoff: 0.0})
5563
YIELD item1, item2, count1, count2, similarity
@@ -60,7 +68,7 @@ ORDER BY similarity DESC
6068
// tag::stream-topk[]
6169
MATCH (p:Person), (c:Cuisine)
6270
OPTIONAL MATCH (p)-[likes:LIKES]->(c)
63-
WITH {item:id(p), weights: collect(coalesce(likes.score, 0))} as userData
71+
WITH {item:id(p), weights: collect(coalesce(likes.score, algo.NaN()))} as userData
6472
WITH collect(userData) as data
6573
CALL algo.similarity.cosine.stream(data, {topK:1, similarityCutoff: 0.0})
6674
YIELD item1, item2, count1, count2, similarity
@@ -71,7 +79,7 @@ ORDER BY from
7179
// tag::write-back[]
7280
MATCH (p:Person), (c:Cuisine)
7381
OPTIONAL MATCH (p)-[likes:LIKES]->(c)
74-
WITH {item:id(p), weights: collect(coalesce(likes.score, 0))} as userData
82+
WITH {item:id(p), weights: collect(coalesce(likes.score, algo.NaN()))} as userData
7583
WITH collect(userData) as data
7684
CALL algo.similarity.cosine(data, {topK: 1, similarityCutoff: 0.1, write:true})
7785
YIELD nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, stdDev, p25, p50, p75, p90, p95, p99, p999, p100
@@ -89,8 +97,33 @@ RETURN cuisine.name AS cuisine
8997
WITH "MATCH (person:Person)-[likes:LIKES]->(c)
9098
RETURN id(person) AS item, id(c) AS category, likes.score AS weight" AS query
9199
CALL algo.similarity.cosine(query, {
92-
graph: "cypher", topK: 1, similarityCutoff: 0.1, write:true
100+
graph: 'cypher', topK: 1, similarityCutoff: 0.1, write:true
93101
})
94102
YIELD nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, stdDev, p95
95103
RETURN nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, p95
96-
// end::cypher-projection[]
104+
// end::cypher-projection[]
105+
106+
107+
// tag::create-sample-embedding-graph[]
108+
109+
MERGE (french:Cuisine {name:'French'}) SET french.embedding = [0.71, 0.33, 0.81, 0.52, 0.41]
110+
MERGE (italian:Cuisine {name:'Italian'}) SET italian.embedding = [0.31, 0.72, 0.58, 0.67, 0.31]
111+
MERGE (indian:Cuisine {name:'Indian'}) SET indian.embedding = [0.43, 0.26, 0.98, 0.51, 0.76]
112+
MERGE (lebanese:Cuisine {name:'Lebanese'}) SET lebanese.embedding = [0.12, 0.23, 0.35, 0.31, 0.39]
113+
MERGE (portuguese:Cuisine {name:'Portuguese'}) SET portuguese.embedding = [0.47, 0.98, 0.81, 0.72, 0.89]
114+
MERGE (british:Cuisine {name:'British'}) SET british.embedding = [0.94, 0.12, 0.23, 0.4, 0.71]
115+
MERGE (mauritian:Cuisine {name:'Mauritian'}) SET mauritian.embedding = [0.31, 0.56, 0.98, 0.21, 0.62]
116+
117+
// end::create-sample-embedding-graph[]
118+
119+
// tag::embedding-graph-stream[]
120+
121+
MATCH (c:Cuisine)
122+
WITH {item:id(c), weights: c.embedding} as userData
123+
WITH collect(userData) as data
124+
CALL algo.similarity.cosine.stream(data, {skipValue: null})
125+
YIELD item1, item2, count1, count2, similarity
126+
RETURN algo.getNodeById(item1).name AS from, algo.getNodeById(item2).name AS to, similarity
127+
ORDER BY similarity DESC
128+
129+
// end::embedding-graph-stream[]

doc/asciidoc/scripts/similarity-euclidean.cypher

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ MERGE (karin)-[:LIKES {score: 7}]->(italian)
3838
// tag::stream[]
3939
MATCH (p:Person), (c:Cuisine)
4040
OPTIONAL MATCH (p)-[likes:LIKES]->(c)
41-
WITH {item:id(p), weights: collect(coalesce(likes.score, 0))} as userData
41+
WITH {item:id(p), weights: collect(coalesce(likes.score, algo.NaN()))} as userData
4242
WITH collect(userData) as data
4343
CALL algo.similarity.euclidean.stream(data)
4444
YIELD item1, item2, count1, count2, similarity
@@ -49,9 +49,9 @@ ORDER BY similarity
4949
// tag::stream-similarity-cutoff[]
5050
MATCH (p:Person), (c:Cuisine)
5151
OPTIONAL MATCH (p)-[likes:LIKES]->(c)
52-
WITH {item:id(p), weights: collect(coalesce(likes.score, 0))} as userData
52+
WITH {item:id(p), weights: collect(coalesce(likes.score, algo.NaN()))} as userData
5353
WITH collect(userData) as data
54-
CALL algo.similarity.euclidean.stream(data, {similarityCutoff: 17.0})
54+
CALL algo.similarity.euclidean.stream(data, {similarityCutoff: 4.0})
5555
YIELD item1, item2, count1, count2, similarity
5656
RETURN algo.getNodeById(item1).name AS from, algo.getNodeById(item2).name AS to, similarity
5757
ORDER BY similarity
@@ -60,7 +60,7 @@ ORDER BY similarity
6060
// tag::stream-topk[]
6161
MATCH (p:Person), (c:Cuisine)
6262
OPTIONAL MATCH (p)-[likes:LIKES]->(c)
63-
WITH {item:id(p), weights: collect(coalesce(likes.score, 0))} as userData
63+
WITH {item:id(p), weights: collect(coalesce(likes.score, algo.NaN()))} as userData
6464
WITH collect(userData) as data
6565
CALL algo.similarity.euclidean.stream(data, {topK:1})
6666
YIELD item1, item2, count1, count2, similarity
@@ -71,7 +71,7 @@ ORDER BY from
7171
// tag::write-back[]
7272
MATCH (p:Person), (c:Cuisine)
7373
OPTIONAL MATCH (p)-[likes:LIKES]->(c)
74-
WITH {item:id(p), weights: collect(coalesce(likes.score, 0))} as userData
74+
WITH {item:id(p), weights: collect(coalesce(likes.score, algo.NaN()))} as userData
7575
WITH collect(userData) as data
7676
CALL algo.similarity.euclidean(data, {topK: 1, write:true})
7777
YIELD nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, stdDev, p25, p50, p75, p90, p95, p99, p999, p100
@@ -89,8 +89,34 @@ RETURN cuisine.name AS cuisine
8989
WITH "MATCH (person:Person)-[likes:LIKES]->(c)
9090
RETURN id(person) AS item, id(c) AS category, likes.score AS weight" AS query
9191
CALL algo.similarity.euclidean(query, {
92-
graph: "cypher", topK: 1, similarityCutoff: 17.0, write:true
92+
graph: 'cypher', topK: 1, similarityCutoff: 4.0, write:true
9393
})
9494
YIELD nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, stdDev, p95
9595
RETURN nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, p95
96-
// end::cypher-projection[]
96+
// end::cypher-projection[]
97+
98+
99+
// tag::create-sample-embedding-graph[]
100+
101+
MERGE (french:Cuisine {name:'French'}) SET french.embedding = [0.71, 0.33, 0.81, 0.52, 0.41]
102+
MERGE (italian:Cuisine {name:'Italian'}) SET italian.embedding = [0.31, 0.72, 0.58, 0.67, 0.31]
103+
MERGE (indian:Cuisine {name:'Indian'}) SET indian.embedding = [0.43, 0.26, 0.98, 0.51, 0.76]
104+
MERGE (lebanese:Cuisine {name:'Lebanese'}) SET lebanese.embedding = [0.12, 0.23, 0.35, 0.31, 0.39]
105+
MERGE (portuguese:Cuisine {name:'Portuguese'}) SET portuguese.embedding = [0.47, 0.98, 0.81, 0.72, 0.89]
106+
MERGE (british:Cuisine {name:'British'}) SET british.embedding = [0.94, 0.12, 0.23, 0.4, 0.71]
107+
MERGE (mauritian:Cuisine {name:'Mauritian'}) SET mauritian.embedding = [0.31, 0.56, 0.98, 0.21, 0.62]
108+
109+
// end::create-sample-embedding-graph[]
110+
111+
// tag::embedding-graph-stream[]
112+
113+
MATCH (c:Cuisine)
114+
WITH {item:id(c), weights: c.embedding} as userData
115+
WITH collect(userData) as data
116+
CALL algo.similarity.euclidean.stream(data, {skipValue: null})
117+
YIELD item1, item2, count1, count2, similarity
118+
RETURN algo.getNodeById(item1).name AS from, algo.getNodeById(item2).name AS to, similarity
119+
ORDER BY similarity DESC
120+
121+
// end::embedding-graph-stream[]
122+

doc/asciidoc/scripts/similarity-pearson.cypher

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ MERGE (praveena)-[:RATED {score: 5}]->(jerry)
2222
MERGE (praveena)-[:RATED {score: 3}]->(home_alone)
2323

2424
MERGE (zhen)-[:RATED {score: 3}]->(home_alone)
25-
MERGE (zhen)-[:RATED {score: 8}]->(good_men)
25+
MERGE (zhen)-[:RATED {score: 5}]->(good_men)
2626
MERGE (zhen)-[:RATED {score: 9}]->(matrix)
2727

2828
MERGE (michael)-[:RATED {score: 8}]->(home_alone)
@@ -31,20 +31,23 @@ MERGE (michael)-[:RATED {score: 9}]->(good_men)
3131

3232
MERGE (arya)-[:RATED {score: 3}]->(top_gun)
3333
MERGE (arya)-[:RATED {score: 10}]->(matrix)
34-
MERGE (arya)-[:RATED {score: 7}]->(jerry)
34+
MERGE (arya)-[:RATED {score: 1}]->(jerry)
3535

3636
MERGE (karin)-[:RATED {score: 9}]->(top_gun)
3737
MERGE (karin)-[:RATED {score: 7}]->(matrix)
38+
MERGE (karin)-[:RATED {score: 2}]->(home_alone)
3839

3940
MERGE (michael)-[:RATED {score: 7}]->(home_alone)
4041
MERGE (michael)-[:RATED {score: 9}]->(good_men)
42+
MERGE (michael)-[:RATED {score: 3}]->(jerry)
43+
MERGE (michael)-[:RATED {score: 4}]->(top_gun)
4144

4245
// end::create-sample-graph[]
4346

4447
// tag::stream[]
4548
MATCH (p:Person), (m:Movie)
4649
OPTIONAL MATCH (p)-[rated:RATED]->(m)
47-
WITH {item:id(p), weights: collect(coalesce(rated.score, 0))} as userData
50+
WITH {item:id(p), weights: collect(coalesce(rated.score, algo.NaN()))} as userData
4851
WITH collect(userData) as data
4952
CALL algo.similarity.pearson.stream(data)
5053
YIELD item1, item2, count1, count2, similarity
@@ -55,7 +58,7 @@ ORDER BY similarity DESC
5558
// tag::stream-similarity-cutoff[]
5659
MATCH (p:Person), (m:Movie)
5760
OPTIONAL MATCH (p)-[rated:RATED]->(m)
58-
WITH {item:id(p), weights: collect(coalesce(rated.score, 0))} as userData
61+
WITH {item:id(p), weights: collect(coalesce(rated.score, algo.NaN()))} as userData
5962
WITH collect(userData) as data
6063
CALL algo.similarity.pearson.stream(data, {similarityCutoff: 0.0})
6164
YIELD item1, item2, count1, count2, similarity
@@ -66,7 +69,7 @@ ORDER BY similarity DESC
6669
// tag::stream-topk[]
6770
MATCH (p:Person), (m:Movie)
6871
OPTIONAL MATCH (p)-[rated:RATED]->(m)
69-
WITH {item:id(p), weights: collect(coalesce(rated.score, 0))} as userData
72+
WITH {item:id(p), weights: collect(coalesce(rated.score, algo.NaN()))} as userData
7073
WITH collect(userData) as data
7174
CALL algo.similarity.pearson.stream(data, {topK:1, similarityCutoff: 0.0})
7275
YIELD item1, item2, count1, count2, similarity
@@ -77,15 +80,15 @@ ORDER BY similarity DESC
7780
// tag::write-back[]
7881
MATCH (p:Person), (m:Movie)
7982
OPTIONAL MATCH (p)-[rated:RATED]->(m)
80-
WITH {item:id(p), weights: collect(coalesce(rated.score, 0))} as userData
83+
WITH {item:id(p), weights: collect(coalesce(rated.score, algo.NaN()))} as userData
8184
WITH collect(userData) as data
8285
CALL algo.similarity.pearson(data, {topK: 1, similarityCutoff: 0.1, write:true})
8386
YIELD nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, stdDev, p25, p50, p75, p90, p95, p99, p999, p100
8487
RETURN nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, p95
8588
// end::write-back[]
8689

8790
// tag::query[]
88-
MATCH (p:Person {name: "Karin"})-[:SIMILAR]->(other),
91+
MATCH (p:Person {name: "Praveena"})-[:SIMILAR]->(other),
8992
(other)-[r:RATED]->(movie)
9093
WHERE not((p)-[:RATED]->(movie)) and r.score >= 8
9194
RETURN movie.name AS movie
@@ -96,8 +99,30 @@ RETURN movie.name AS movie
9699
WITH "MATCH (person:Person)-[likes:LIKES]->(c)
97100
RETURN id(person) AS item, id(c) AS category, likes.score AS weight" AS query
98101
CALL algo.similarity.pearson(query, {
99-
graph: "cypher", topK: 1, similarityCutoff: 0.1, write:true
102+
graph: 'cypher', topK: 1, similarityCutoff: 0.1, write:true
100103
})
101104
YIELD nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, stdDev, p95
102105
RETURN nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, p95
103-
// end::cypher-projection[]
106+
// end::cypher-projection[]
107+
108+
// tag::create-sample-embedding-graph[]
109+
110+
MERGE (home_alone:Movie {name:'Home Alone'}) SET home_alone.embedding = [0.71, 0.33, 0.81, 0.52, 0.41]
111+
MERGE (matrix:Movie {name:'The Matrix'}) SET matrix.embedding = [0.31, 0.72, 0.58, 0.67, 0.31]
112+
MERGE (good_men:Movie {name:'A Few Good Men'}) SET good_men.embedding = [0.43, 0.26, 0.98, 0.51, 0.76]
113+
MERGE (top_gun:Movie {name:'Top Gun'}) SET top_gun.embedding = [0.12, 0.23, 0.35, 0.31, 0.3]
114+
MERGE (jerry:Movie {name:'Jerry Maguire'}) SET jerry.embedding = [0.47, 0.98, 0.81, 0.72, 0]
115+
116+
// end::create-sample-embedding-graph[]
117+
118+
// tag::embedding-graph-stream[]
119+
120+
MATCH (m:Movie)
121+
WITH {item:id(m), weights: m.embedding} as userData
122+
WITH collect(userData) as data
123+
CALL algo.similarity.pearson.stream(data, {skipValue: null})
124+
YIELD item1, item2, count1, count2, similarity
125+
RETURN algo.getNodeById(item1).name AS from, algo.getNodeById(item2).name AS to, similarity
126+
ORDER BY similarity DESC
127+
128+
// end::embedding-graph-stream[]

0 commit comments

Comments
 (0)