Open paul-shannon opened 4 years ago
@ColinFay sorry to pester but may I inquire - without being an ungrateful wretch :} - does anyone have the time to fix bugs and otherwise work on your good package?
[Hold on, I just found the data. I'll get back to you in a moment]
Hi Paul, I'm not the developer nor maintainer of this app, but I'd tried to take a look at your issue. It's difficult to do because the elements you provide do not qualify as a reproducible example, as you don't provide the Neo4J data you run your query against.
I think that the bug comes from the function parse_row( ), which is used by call_neo4j( ) to parse the results Neo4J sends back when those are arrays. Specifically, it seems the first parsed row(s?) contain numeric values in column v4
and a subsequent row has a character variable in column V4
, which is incompatible type with the previous values.
I'm afraid that the only way to solve your issue would be to understand what actually comes out of Neo4J. Could you please try to run the cypher query directly in a Neo4J client, and copy the output here. Otherwise, I would need to get the data you run the query against to reproduce the output.
Hi again. Here is a reproducible example:
# Install dev verion from github
install.packages("remotes")
remotes::install_github("neo4j-rstats/neo4r")
library(neo4r)
library(tibble)
# Connect to the Neo4J DB running on Neo4J desktop
con <- neo4j_api$new(
url = "http://localhost:7474",
user = "neo4j",
password = "password"
)
load_csv(url = "https://raw.githubusercontent.com/neo4j-graph-analytics/book/master/data/transport-nodes.csv",
con = con, header = TRUE, periodic_commit = 50,
as = "row", on_load = 'MERGE (place:Place {id:row.id})
SET place.latitude = toFloat(row.latitude),
place.longitude = toFloat(row.latitude),
place.population = toInteger(row.population)')
load_csv(url = "https://raw.githubusercontent.com/neo4j-graph-analytics/book/master/data/transport-relationships.csv",
con = con, header = TRUE, periodic_commit = 50,
as = "row", on_load = 'MATCH (origin:Place {id: row.src})
MATCH (destination:Place {id: row.dst})
MERGE (origin)-[:EROAD {distance: toInteger(row.cost)}]->(destination)')
query <- 'MATCH (start:Place {id:"Gouda"}),
(end:Place {id:"Felixstowe"})
CALL algo.kShortestPaths.stream(start, end, 5, "distance")
YIELD index, nodeIds, path, costs RETURN index, [node in algo.getNodesById(nodeIds[1..-1]) | node.id]
AS via, reduce(acc=0.0, cost in costs | acc + cost) AS totalCost'
res <- call_neo4j(query, con = con, type = "row")
This produces the error code mentioned by @paul-shannon :
Error: Column 'V4' can't be converted from numeric to character
However, the following returns a correct JSON:
res <- call_neo4j(query, con = con, output = "json")
In Neo4J, the results looks like:
index | via | totalCost |
---|---|---|
0 | ["Rotterdam", "Hoek van Holland"] | 265.0 |
1 | ["Den Haag", "Hoek van Holland"] | 266.0 |
2 | ["Rotterdam", "Den Haag", "Hoek van Holland"] | 285.0 |
3 | ["Den Haag", "Rotterdam", "Hoek van Holland"] | 298.0 |
4 | ["Utrecht", "Amsterdam", "Den Haag", "Hoek van Holland"] | 374.0 |
The problem stems from the fact that, due to the transformations included at the end of the cypher query, the second column (named "via") contains nested values. This case is not handled by the parsing api programmed by @ColinFay and cannot automatically be processed as a tibble. I really don't know if it would even be possible to rewrite the parse_raw( ) function to handle such cases, as the Neo4J output corresponds in essence to a list object in R.
@fBedecarrats @ColinFay Many thanks, Florent, for creating the reproducible example. I agree: a perfect transformation from all Neo4j results into R tibbles might not be attainable.
Colin mentions issue 66 adding a method to the neo4r class which forgoes that step, instead just returning a list. Maybe that would help out in cases such as this one.
Many thanks for this package - it is very useful. Here I report an apparent bug which I hope you can help with.
I am working my way through the 2019 edition of "Graph Algorithms: Practical Examples in Apache Spark and Neo4j" by Needham and Hodler from O'Reilly. The example on page 59 is of Yen's shortest path algorithm, which I call like this:
with this result:
this traceback:
and this sessionInfo()