Spring Data | Neo4J | Querying for the path in the correct order

519 Views Asked by At

Versions:

<dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-ogm-core</artifactId>
            <version>2.1.1</version>
        </dependency>

        <dependency> <!-- If you're using the HTTP driver -->
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-ogm-http-driver</artifactId>
            <version>2.1.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-neo4j -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-neo4j</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>

Here are my entities:

@Data
@NodeEntity
@EqualsAndHashCode(exclude = {"operatedByBuses"})
@ToString(of = {"name"})
public class BusStop {
    @GraphId
    private Long graphId;

    @Index(unique = true, primary = true)
    private String name;

    private String pincode;

    private String landmark;

    private String[] latlong;

    @Relationship(type = "OPERATED_BY")
    private Set<OperatedByBus> operatedByBuses = new HashSet<>();
}

@Data
@RelationshipEntity(type = "OPERATED_BY")
@ToString(of = "displayName")
public class OperatedByBus {

    @GraphId
    private Long id;

    @StartNode
    private BusStop origin;

    @EndNode
    private BusStop destination;
}

I'm trying to get the routes between A and D for which I need the result as A,B,C and D in the correct order and then I'll get the buses in each object.

This is my cypher:

String findBuses = "MATCH p=shortestPath((o:BusStop)-[buses*1..40]->(d:BusStop))\n" +
                "WHERE o.name =~ '(?i).*ABC Bus Stand.*'\n" +
                "  AND d.name =~ '(?i).*XYZ Bus Stand.*'\n" +
                "RETURN p";

        Iterable<BusStop> busstops = session.query(BusStop.class, findBuses, Collections.emptyMap());
        System.out.println(busstops);

        for (BusStop busStop : busstops) {
            System.out.println(busStop.getName());
            System.out.println("\t " + busStop.getOperatedByBuses());
        }

But the results are not in the right order. I see results as D,C,A,B (or some random order) as opposed to A,B,C,D.

One way I can think of is add an attribute to the OperatedByBus say int legId and then order by legId in my query. Not sure if this is the best way.

Anything I'm missing?

1

There are 1 best solutions below

0
On BEST ANSWER

Modify your query as follows:

MATCH p=shortestPath((o:BusStop)-[buses*1..40]->(d:BusStop))
WHERE 
  o.name =~ '(?i).*ABC Bus Stand.*' AND
  d.name =~ '(?i).*XYZ Bus Stand.*'
RETURN nodes(p) as busStops,relationships(p)

note that your query may return multiple rows, when the where clause matches multiple nodes.

Then use session.query(findBuses, Collections.emptyMap()); instead. The result type is org.neo4j.ogm.model.Result, use following to get individual results:

Iterable<Map<String, Object>> result.queryResults();
.. iterate over results
   // to get a `busStops` for single path as collection, which should be in order
   .. (Collection<BusStop>) item.get("busStops");