Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ package com.redislabs.redisgraph;

import com.redislabs.redisgraph.graph_entities.Edge;
import com.redislabs.redisgraph.graph_entities.Node;
import com.redislabs.redisgraph.graph_entities.Path;
import com.redislabs.redisgraph.impl.api.RedisGraph;

import java.util.List;
Expand All @@ -115,6 +116,15 @@ public class RedisGraphExample {
System.out.println(record.toString());
}

resultSet = graph.query("social", "MATCH p = (:person)-[:knows]->(:person) RETURN p");
while(resultSet.hasNext()) {
Record record = resultSet.next();
Path p = record.getValue("p");

// More path API at Javadoc.
System.out.println(p.nodeCount());
}

// delete graph
graph.deleteGraph("social");

Expand Down
20 changes: 19 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,25 @@
<version>1.6.6</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId>
<version>3.1.10</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
Expand Down
118 changes: 118 additions & 0 deletions src/main/java/com/redislabs/redisgraph/graph_entities/Path.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.redislabs.redisgraph.graph_entities;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* This class represents a path in the graph.
*/
public final class Path {

private final List<Node> nodes;
private final List<Edge> edges;


/**
* Parametrized constructor
* @param nodes - List of nodes.
* @param edges - List of edges.
*/
public Path(List<Node> nodes, List<Edge> edges) {
this.nodes = nodes;
this.edges = edges;
}

/**
* Returns the nodes of the path.
* @return List of nodes.
*/
public List<Node> getNodes() {
return nodes;
}

/**
* Returns the edges of the path.
* @return List of edges.
*/
public List<Edge> getEdges() {
return edges;
}

/**
* Returns the length of the path - number of edges.
* @return Number of edges.
*/
public int length() {
return edges.size();
}

/**
* Return the number of nodes in the path.
* @return Number of nodes.
*/
public int nodeCount(){
return nodes.size();
}

/**
* Returns the first node in the path.
* @return First nodes in the path.
* @throws IndexOutOfBoundsException if the path is empty.
*/
public Node firstNode(){
return nodes.get(0);
}

/**
* Returns the last node in the path.
* @return Last nodes in the path.
* @throws IndexOutOfBoundsException if the path is empty.
*/
public Node lastNode(){
return nodes.get(nodes.size() - 1);
}

/**
* Returns a node with specified index in the path.
* @return Node.
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= nodesCount()})
*/
public Node getNode(int index){
return nodes.get(index);
}

/**
* Returns an edge with specified index in the path.
* @return Edge.
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= length()})
*/
public Edge getEdge(int index){
return edges.get(index);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Path path = (Path) o;
return Objects.equals(nodes, path.nodes) &&
Objects.equals(edges, path.edges);
}

@Override
public int hashCode() {
return Objects.hash(nodes, edges);
}

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Path{");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return "Path{nodes=" + nodes + " edges=" + edges + "}";

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto-generated. I like string builder better than string appends.

sb.append("nodes=").append(nodes);
sb.append(", edges=").append(edges);
sb.append('}');
return sb.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
import com.redislabs.redisgraph.ResultSet;
import com.redislabs.redisgraph.Statistics;
import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeException;
import com.redislabs.redisgraph.graph_entities.Edge;
import com.redislabs.redisgraph.graph_entities.GraphEntity;
import com.redislabs.redisgraph.graph_entities.Node;
import com.redislabs.redisgraph.graph_entities.Property;
import com.redislabs.redisgraph.graph_entities.*;
import com.redislabs.redisgraph.impl.graph_cache.GraphCache;
import redis.clients.jedis.util.SafeEncoder;
import redis.clients.jedis.exceptions.JedisDataException;
Expand Down Expand Up @@ -245,12 +242,21 @@ private Object deserializeScalar(List<Object> rawScalarData) {
return deserializeNode((List<Object>) obj);
case VALUE_EDGE:
return deserializeEdge((List<Object>) obj);
case VALUE_PATH:
return deserializePath(obj);
case VALUE_UNKNOWN:
default:
return obj;
}
}

private Path deserializePath(Object rawScalarData) {
List<List<Object>> array = (List<List<Object>>) rawScalarData;
List<Node> nodes = (List<Node>) deserializeScalar(array.get(0));
List<Edge> edges = (List<Edge>) deserializeScalar(array.get(1));
return new Path(nodes, edges);
}

private List<Object> deserializeArray(Object rawScalarData) {
List<List<Object>> array = (List<List<Object>>) rawScalarData;
List<Object> res = new ArrayList<>(array.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ enum ResultSetScalarTypes {
VALUE_DOUBLE,
VALUE_ARRAY,
VALUE_EDGE,
VALUE_NODE;
VALUE_NODE,
VALUE_PATH;


static ResultSetScalarTypes[] values = values();
Expand Down
56 changes: 49 additions & 7 deletions src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
package com.redislabs.redisgraph;


import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import com.redislabs.redisgraph.graph_entities.Edge;
import com.redislabs.redisgraph.graph_entities.Node;
import com.redislabs.redisgraph.graph_entities.Path;
import com.redislabs.redisgraph.graph_entities.Property;
import com.redislabs.redisgraph.impl.api.RedisGraph;
import com.redislabs.redisgraph.impl.resultset.ResultSetImpl;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.redislabs.redisgraph.test.utils.PathBuilder;
import org.junit.*;

import com.redislabs.redisgraph.Statistics.Label;
import org.junit.rules.ExpectedException;

import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*;

public class RedisGraphAPITest {

private RedisGraphContextGenerator api;

public RedisGraphAPITest() {
Expand Down Expand Up @@ -878,4 +877,47 @@ record = resultSet.next();

}

@Test
public void testPath(){
List<Node> nodes = new ArrayList<>(3);
for(int i =0; i < 3; i++){
Node node = new Node();
node.setId(i);
node.addLabel("L1");
nodes.add(node);
}

List<Edge> edges = new ArrayList<>(2);
for(int i =0; i <2; i++){
Edge edge = new Edge();
edge.setId(i);
edge.setRelationshipType("R1");
edge.setSource(i);
edge.setDestination(i + 1);
edges.add(edge);
}

Set<Path> expectedPaths = new HashSet<>();

Path path01 = new PathBuilder(2).append(nodes.get(0)).append(edges.get(0)).append(nodes.get(1)).build();
Path path12 = new PathBuilder(2).append(nodes.get(1)).append(edges.get(1)).append(nodes.get(2)).build();
Path path02 = new PathBuilder(3).append(nodes.get(0)).append(edges.get(0)).append(nodes.get(1)).append(edges.get(1)).append(nodes.get(2)).build();

expectedPaths.add(path01);
expectedPaths.add(path12);
expectedPaths.add(path02);

api.query("social", "CREATE (:L1)-[:R1]->(:L1)-[:R1]->(:L1)");

ResultSet resultSet = api.query("social", "MATCH p = (:L1)-[:R1*]->(:L1) RETURN p");

Assert.assertEquals(expectedPaths.size(), resultSet.size());
for(int i =0; i < resultSet.size(); i++){
Path p = resultSet.next().getValue("p");
Assert.assertTrue(expectedPaths.contains(p));
expectedPaths.remove(p);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.redislabs.redisgraph.graph_entities;

import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.junit.jupiter.api.Assertions.*;

public class PathTest {

private Node buildNode(int id){
Node n = new Node();
n.setId(0);
return n;
}

private Edge buildEdge(int id, int src, int dst){
Edge e = new Edge();
e.setId(id);
e.setSource(src);
e.setDestination(dst);
return e;
}

private List<Node> buildNodeArray(int size) {
List<Node> nodes = new ArrayList<>();
return IntStream.range(0, size).mapToObj(i -> buildNode(i)).collect(Collectors.toList());
}

private List<Edge> buildEdgeArray(int size){
List<Node> nodes = new ArrayList<>();
return IntStream.range(0, size).mapToObj(i -> buildEdge(i, i, i+1)).collect(Collectors.toList());
}

private Path buildPath(int nodeCount){
return new Path(buildNodeArray(nodeCount), buildEdgeArray(nodeCount-1));
}

@Test
public void testEmptyPath(){
Path path = buildPath(0);
assertEquals(0, path.length());
assertEquals(0, path.nodeCount());
assertThrows(IndexOutOfBoundsException.class, ()->path.getNode(0));
assertThrows(IndexOutOfBoundsException.class, ()->path.getEdge(0));
}

@Test
public void testSingleNodePath(){
Path path = buildPath(1);
assertEquals(0, path.length());
assertEquals(1, path.nodeCount());
Node n = new Node();
n.setId(0);
assertEquals(n, path.firstNode());
assertEquals(n, path.lastNode());
assertEquals(n, path.getNode(0));
}

@Test
public void testRandomLengthPath(){
int nodeCount = ThreadLocalRandom.current().nextInt(2, 100 + 1);
Path path = buildPath(nodeCount);
assertEquals(buildNodeArray(nodeCount), path.getNodes());
assertEquals(buildEdgeArray(nodeCount-1), path.getEdges());
assertDoesNotThrow(()->path.getEdge(0));
}

@Test
public void hashCodeEqualTest(){
EqualsVerifier.forClass(Path.class).verify();
}
}
Loading