I have the following query and it's working perfectly when I execute it on Neoj4 Browser:
MATCH (p1:Book{friendlyUrl:"a-modern-witch"})-[r:BOOK_ADDED_TO_CATALOG]->(catalog1:Catalog)
WITH p1, collect(id(catalog1)) AS p1Catalog
MATCH (p2:Book)-[:BOOK_ADDED_TO_CATALOG]->(catalog2:Catalog)
WHERE p1 <> p2
WITH p1, p1Catalog, p2, collect(id(catalog2)) AS p2Catalog
RETURN p1.title AS from,
p2.title AS to,
algo.similarity.jaccard(p1Catalog, p2Catalog) AS similarity
ORDER BY similarity DESC
I want to transform it to c# code and I am doing it like this:
var result = _graphClient.Cypher
.Match ("(p1:Book{friendlyUrl:'a-modern-witch'})-[r:BOOK_ADDED_TO_CATALOG]->(catalog1:Catalog)")
.With ("p1, collect(id(catalog1)) AS p1Catalog")
.Match ("(p2:Book)-[:BOOK_ADDED_TO_CATALOG]->(catalog2:Catalog)")
.Where ("p1 <> p2")
.With ("p1, p1Catalog, p2, collect(id(catalog2)) AS p2Catalog")
.Call ("algo.similarity.jaccard(p1Catalog, p2Catalog)")
.Yield ("value AS similiarity")
.Return ((p1, p2, similiarity) => new {
bk1 = p1.As<BookDetailsDto> (),
bk2 = p2.As<BookDetailsDto> (),
})
.Limit (10);
Unfortunately when I call it through the API I am getting the following error:
An unhandled exception occurred while processing the request. NeoException: SyntaxException: Type mismatch: expected List, List or List but was List (line 6, column 30 (offset: 327)) CALL algo.similarity.jaccard(p1Catalog, p2Catalog)
The cypher query that is build by neo4jClient is quite different than the original one on the top:
MATCH (p1:Book{friendlyUrl:'harry-potter-and-the-deathly-hallows'})-[r:BOOK_ADDED_TO_CATALOG]->(catalog1:Catalog)
WITH p1, collect(id(catalog1)) AS p1Catalog
MATCH (p2:Book)-[:BOOK_ADDED_TO_CATALOG]->(catalog2:Catalog)
WHERE p1 <> p2
WITH p1, p1Catalog, p2, collect(id(catalog2)) AS p2Catalog
CALL algo.similarity.jaccard(p1Catalog, p2Catalog)
YIELD value AS similiarity
RETURN p1 AS bk, p2 AS bk2
LIMIT 10
OK, so there are two parts to this - why the Cypher doesn't match, and what the error means - they're both related, but we'll tackle the Cypher difference first - as that'll get your results.
In your Cypher you don't do a CALL
- you simply RETURN
the Jaccard, so to get a true reflection of your Cypher, you'd want:
var result = _graphClient.Cypher
.Match ("(p1:Book{friendlyUrl:'a-modern-witch'})-[r:BOOK_ADDED_TO_CATALOG]->(catalog1:Catalog)")
.With ("p1, collect(id(catalog1)) AS p1Catalog")
.Match ("(p2:Book)-[:BOOK_ADDED_TO_CATALOG]->(catalog2:Catalog)")
.Where ("p1 <> p2")
.With ("p1, p1Catalog, p2, collect(id(catalog2)) AS p2Catalog")
.Return ((p1, p2, similiarity) => new {
bk1 = p1.As<BookDetailsDto> (),
bk2 = p2.As<BookDetailsDto> (),
similarity = Return.As<double>("algo.similarity.jaccard(p1Catalog, p2Catalog)")
})
.OrderByDescending("similarity")
.Limit (10);
The key bit in there is the removal of the .Call
err, call, and the use of Return.As<>
for your algorithm call.
The second part - (the error message you get) is directly related to this subtle change, by using CALL
you switch from using the 'Function' version of Jaccard to the 'Prodedure' version - and they have different signatures, the Function version looks like this:
"algo.similarity.jaccard(vector1 :: LIST? OF NUMBER?, vector2 :: LIST? OF NUMBER?) :: (FLOAT?)"
So it expects a LIST? OF NUMBER?
what your COLLECT(id(catalog))
outputs. You can get this information by running the following Cypher in your browser:
CALL dbms.functions() YIELD name, signature, description
WHERE name CONTAINS 'jaccard'
RETURN *
Now, the Prodedure version looks like this:
"algo.similarity.jaccard(data = null :: LIST? OF MAP?, config = {} :: MAP?) :: (nodes :: INTEGER?, sourceNodes :: INTEGER?, targetNodes :: INTEGER?, similarityPairs :: INTEGER?, computations :: INTEGER?, write :: BOOLEAN?, writeRelationshipType :: STRING?, writeProperty :: STRING?, min :: FLOAT?, max :: FLOAT?, mean :: FLOAT?, stdDev :: FLOAT?, p25 :: FLOAT?, p50 :: FLOAT?, p75 :: FLOAT?, p90 :: FLOAT?, p95 :: FLOAT?, p99 :: FLOAT?, p999 :: FLOAT?, p100 :: FLOAT?)"
Which is looking for a LIST? OF MAP?
- which is not what you're getting - hence the error message.
Cypher for this is:
CALL dbms.procedures() YIELD name, signature, description
WHERE name CONTAINS 'jaccard'
RETURN *
Anyhews - the first C# code should get you sorted.