Hi all,
I'm trying to write a procedure that uses Dijkstra's algorithm to find the
shortest weighted path between two nodes. All nodes in that path should
have specific properties and values, otherwise the path is invalid, and the
algorithm should continue searching for the next shortest weighted path.
I'm trying to tackle this using PathExpanderBuilder.addNodeFilter, as
follows:
PathExpanderBuilder builder = PathExpanderBuilder.allTypesAndDirections();
builder.addNodeFilter(
node -> !node.hasProperty(prop1) ||
node.getProperty(prop1) instanceof Long &&
(long) node.getProperty(prop1) < prop1Value
);
When I run the procedure, the filter doesn't take action, and invalid
paths end up returning in the query result.
Below is my full procedure code:
public class Demo {
@Procedure
@Description("apoc.algo.multiDijkstraWithDefaultWeight(startNode, endNode,
" +
"'distance', 10, 'prop1', 2, 'prop2', [100, 200], 'prop3') " +
" YIELD path, weight - run dijkstra with relationship property name
as cost function" +
" and a default weight if the property does not exist")
public Stream<WeightedPathResult> multiDijkstraWithDefaultWeight(
@Name("startNode") Node startNode,
@Name("endNode") Node endNode,
@Name("weightPropertyName") String weightPropertyName,
@Name("defaultWeight") double defaultWeight,
@Name("longPropName") String longPropName,
@Name("longPropValue") long longPropValue,
@Name("listPropName") String listPropName,
@Name("listPropValues") List<Long> listPropValues,
@Name("boolPropName") String boolPropName) {
PathFinder<WeightedPath> algo = GraphAlgoFactory.dijkstra(
buildPathExpanderByPermissions(longPropName, longPropValue,
listPropName, listPropValues, boolPropName),
(relationship, direction) ->
convertToDouble(relationship.getProperty(weightPropertyName, defaultWeight))
);
return WeightedPathResult.streamWeightedPathResult(startNode, endNode,
algo);
}
private double convertToDouble(Object property) {
if (property instanceof Double)
return (double) property;
else if (property instanceof Long)
return ((Long) property).doubleValue();
else if (property instanceof Integer)
return ((Integer) property).doubleValue();
return 1;
}
private PathExpander<Object> buildPathExpanderByPermissions(
String longPropName,
long longPropValue,
String listPropName,
List<Long> listPropValues,
String boolPropName
) {
PathExpanderBuilder builder =
PathExpanderBuilder.allTypesAndDirections();
builder.addNodeFilter(
node -> !node.hasProperty(longPropName) ||
node.getProperty(longPropName) instanceof Long &&
(long) node.getProperty(longPropName) <
longPropValue
);
builder.addNodeFilter(
node -> {
try {
return !node.hasProperty(listPropName) ||
(boolean) node.getProperty(boolPropName, false)
||
!Collections.disjoint((List<Long>)
node.getProperty(listPropName), listPropValues);
}
catch (Exception e){
return false;
}
}
);
return builder.build();
}
}
Your help is greatly appreciated.
--
You received this message because you are subscribed to the Google Groups
"Neo4j" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.