neo4j / graph-data-science

Source code for the Neo4j Graph Data Science library of graph algorithms.
https://neo4j.com/docs/graph-data-science/current/
Other
629 stars 161 forks source link

Relationship Projection default property value not accepted when using gds.alpha.shortestPath #93

Closed jetsloan closed 3 years ago

jetsloan commented 3 years ago

Hi Team,

I'm trying to use the gds.alpha.shortestPath to find the shortest path based on relationship types. I don't have predefined weights for the relationships because in my case the weight is contextual, so I want to use the type and give it a default weight. I'm not sure if this is a bug or simply not supported, from my understanding of the documentation it seems like it's possible.

Steps to reproduce:

  1. Create the unweighted relationship tree: CREATE (a:Loc {name: 'A'}), (b:Loc {name: 'B'}), (c:Loc {name: 'C'}), (d:Loc {name: 'D'}), (e:Loc {name: 'E'}), (f:Loc {name: 'F'}), (a)-[:PATH]->(b), (a)-[:ROAD]->(c), (a)-[:DENSE]->(d), (b)-[:ROAD]->(d), (c)-[:ROAD]->(d), (c)-[:PATH]->(e), (d)-[:ROAD]->(e), (d)-[:ROAD]->(f), (e)-[:DENSE]->(f);

  2. Specify the query with default weights: MATCH (start:Loc {name: 'A'}) MATCH (end:Loc {name: 'F'}) CALL gds.alpha.shortestPath.stream({ nodeProjection: 'Loc', relationshipProjection: { ROAD: { type: 'ROAD', properties: { cost: { property: 'cost', defaultValue: 1.0 } }, orientation: 'UNDIRECTED' }, PATH: { type: 'PATH', properties: { cost: { property: 'cost', defaultValue: 2.0 } }, orientation: 'UNDIRECTED' }, DENSE: { type: 'DENSE', properties: { cost: { property: 'cost', defaultValue: 5.0 } }, orientation: 'UNDIRECTED' } }, startNode: start, endNode: end, relationshipWeightProperty: 'cost' }) YIELD nodeId, cost RETURN gds.util.asNode(nodeId).name AS name, cost

Expected result - The default values should allow the query to run and return the shortest path based on the relationship projection I specified.

Actual result - Failed to invoke procedure gds.alpha.shortestPath.stream: Caused by: java.lang.IllegalArgumentException: Relationship properties not found: 'cost' (if you meant to count parallel relationships, use property:'*').

This would be really powerful to be able to give a relationship a cost based on a context.

I am using neo4j-graph-data-science 1.4.0 and neo4j 4.1.3 Enterprise

knutwalker commented 3 years ago

Hi 👋,

thanks for the report. This is indeed an interesting use-case and it is a bit at odds with the way properties work in GDS. We require that the specified property exists at least somewhere in the graph. This is to prevent mistakes due to typos or reconfiguration. If one was to mistype their property names in the projection, GDS would silently run and produce wrong results and it might take a while to notice that error. So instead, we opt for an early error at the cost of not directly supporting your use-case.

You can work around that restriction by creating the non-existing property in the database like so:

CALL db.createProperty('cost');

After that, you can run the shortestPath query using cost as a property in the way that you intended to run it.

Hope that helps,

Cheers

jetsloan commented 3 years ago

Hi,

Thanks for the response.

This works for what I was looking for that you very much.

It makes sense to prevent errors, I understand the approach taken.

All the best,

Jethro