diff --git a/.gitignore b/.gitignore index 6143e53..5c4919e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ # Compiled class file *.class +/bin/ +/target/ +/test-output/ + # Log file *.log @@ -20,3 +24,7 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +#eclispe +.classpath +.project diff --git a/.idea/libraries/Maven__redis_clients_jedis_3_0_0.xml b/.idea/libraries/Maven__redis_clients_jedis_3_0_0.xml deleted file mode 100644 index e62209b..0000000 --- a/.idea/libraries/Maven__redis_clients_jedis_3_0_0.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0218bba..d831dc0 100644 --- a/pom.xml +++ b/pom.xml @@ -9,30 +9,20 @@ 1.0.0 - org.testng - testng - 6.8 + junit + junit + 4.12 + test - - org.apache.commons commons-pool2 2.0 - redis.clients - jedis - 3.0.0 + com.redislabs + jredisearch-jedis + 3.0.0-20180508 - - - - - - - - - - \ No newline at end of file + diff --git a/src/main/java/com/redislabs/redisgraph/Client.java b/src/main/java/com/redislabs/redisgraph/Client.java deleted file mode 100644 index 1720f15..0000000 --- a/src/main/java/com/redislabs/redisgraph/Client.java +++ /dev/null @@ -1,231 +0,0 @@ -package com.redislabs.redisgraph; - -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -public class Client { - private JedisPool pool; - - Jedis _conn() { - return pool.getResource(); - } - - public Client(String host, int port) { - pool = new JedisPool(host, port); - } - - public String createNode(String graph, String label, Object... attributes) { - Jedis conn = _conn(); - - List args = new ArrayList(2 + attributes.length); - args.add(graph); - args.add(label); - - for(Object attr: attributes) { - args.add(attr.toString()); - } - - String[] stringArgs = args.toArray(new String[args.size()]); - - String nodeId = conn.getClient() - .sendCommand(Commands.Command.CREATENODE, stringArgs) - .getBulkReply(); - - conn.close(); - return nodeId; - } - - public String createNode(String graph, Object... attributes) { - Jedis conn = _conn(); - - List args = new ArrayList(1 + attributes.length); - args.add(graph); - - for(Object attr: attributes) { - args.add(attr.toString()); - } - - String[] stringArgs = args.toArray(new String[args.size()]); - - String nodeId = conn.getClient() - .sendCommand(Commands.Command.CREATENODE, stringArgs) - .getBulkReply(); - - conn.close(); - return nodeId; - } - - public String connectNodes(String graph, String srcNodeID, String relation, String destNodeID, Object... attributes) { - Jedis conn = _conn(); - - List args = new ArrayList(4 + attributes.length); - args.add(graph); - args.add(srcNodeID); - args.add(relation); - args.add(destNodeID); - - for(Object attr: attributes) { - args.add(attr.toString()); - } - - String[] stringArgs = args.toArray(new String[args.size()]); - - String edgeId = conn.getClient() - .sendCommand(Commands.Command.ADDEDGE, stringArgs) - .getBulkReply(); - - conn.close(); - return edgeId; - } - - public List> getNodes(String graphId, Object... ids) { - Jedis conn = _conn(); - - List args = new ArrayList(2); - args.add(graphId); - for(Object id: ids) { - args.add(id.toString()); - } - - String[] stringArgs = args.toArray(new String[args.size()]); - List replay; - try { - replay = conn.getClient() - .sendCommand(Commands.Command.GETNODES, stringArgs) - .getMultiBulkReply(); - } catch(ClassCastException e) { - return null; - } - - List> nodes = new ArrayList>(); - - int numberOfNodes = Integer.parseInt(replay.get(replay.size()-1)); - int offset = 0; - - for(int i = 0; i < numberOfNodes; i++) { - int numberOfProperties = Integer.parseInt(replay.get(offset)); - offset++; - - HashMap nodeAttributes = new HashMap(numberOfProperties/2); - nodes.add(nodeAttributes); - for(int j = 0; j < numberOfProperties; j+=2) { - String key = replay.get(offset + j); - String value = replay.get(offset + j + 1); - nodeAttributes.put(key, value); - } - - offset += numberOfProperties; - } - - conn.close(); - return nodes; - } - - public List> getEdges(String graphId, Object... ids) { - Jedis conn = _conn(); - - List args = new ArrayList(2); - args.add(graphId); - for(Object id : ids) { - args.add(id.toString()); - } - - String[] stringArgs = args.toArray(new String[args.size()]); - List replay; - - try { - replay = conn.getClient() - .sendCommand(Commands.Command.GETEDGES, stringArgs) - .getMultiBulkReply(); - } catch (ClassCastException e) { - return null; - } - - List> edges = new ArrayList>(); - - int numberOfEdges = Integer.parseInt(replay.get(replay.size()-1)); - int offset = 0; - - for(int i = 0; i < numberOfEdges; i++) { - int numberOfProperties = Integer.parseInt(replay.get(offset)); - offset++; - - HashMap edgeAttributes = new HashMap(numberOfProperties/2); - edges.add(edgeAttributes); - for(int j = 0; j < numberOfProperties; j+=2) { - String key = replay.get(offset + j); - String value = replay.get(offset + j + 1); - edgeAttributes.put(key, value); - } - - offset += numberOfProperties; - } - - conn.close(); - return edges; - } - - public List getNodeEdges(String graphId, String nodeId, String edgeType, int direction) { - Jedis conn = _conn(); - List args = new ArrayList(4); - args.add(graphId); - args.add(nodeId); - args.add(edgeType); - args.add(String.valueOf(direction)); - - String[] stringArgs = args.toArray(new String[args.size()]); - - List edges = conn.getClient() - .sendCommand(Commands.Command.GETNODEEDGES, stringArgs) - .getMultiBulkReply(); - - conn.close(); - return edges; - } - - public List getNeighbours(String graphId, String nodeId, String edgeType, int direction) { - Jedis conn = _conn(); - List args = new ArrayList(4); - args.add(graphId); - args.add(nodeId); - args.add(edgeType); - args.add(String.valueOf(direction)); - - String[] stringArgs = args.toArray(new String[args.size()]); - - List neighbours = conn.getClient() - .sendCommand(Commands.Command.GETNEIGHBOURS, stringArgs) - .getMultiBulkReply(); - - conn.close(); - return neighbours; - } - - public ResultSet query(String graphId, String query) { - Jedis conn = _conn(); - - List resp = conn.getClient() - .sendCommand(Commands.Command.QUERY, graphId, query) - .getObjectMultiBulkReply(); - - conn.close(); - return new ResultSet(resp); - } - - public boolean setProperty(String elementId, String key, Object value) { - Jedis conn = _conn(); - return conn.hset(elementId, key, value.toString()) == 1; - } - - public void deleteGraph(String graph) { - Jedis conn = _conn(); - conn.getClient() - .sendCommand(Commands.Command.DELETEGRAPH, graph) - .getStatusCodeReply(); - conn.close(); - } -} diff --git a/src/main/java/com/redislabs/redisgraph/Command.java b/src/main/java/com/redislabs/redisgraph/Command.java new file mode 100644 index 0000000..4e9f695 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/Command.java @@ -0,0 +1,22 @@ +package com.redislabs.redisgraph; +import redis.clients.jedis.util.SafeEncoder; +import redis.clients.jedis.commands.ProtocolCommand; + +/** + * + * + * + */ +public enum Command implements ProtocolCommand { + QUERY("graph.QUERY"); + + private final byte[] raw; + + Command(String alt) { + raw = SafeEncoder.encode(alt); + } + + public byte[] getRaw() { + return raw; + } +} diff --git a/src/main/java/com/redislabs/redisgraph/Commands.java b/src/main/java/com/redislabs/redisgraph/Commands.java deleted file mode 100644 index 447366a..0000000 --- a/src/main/java/com/redislabs/redisgraph/Commands.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.redislabs.redisgraph; -import redis.clients.util.SafeEncoder; -import redis.clients.jedis.commands.ProtocolCommand; - - -public class Commands { - public enum Command implements ProtocolCommand { - CREATENODE("graph.CREATENODE"), - ADDEDGE("graph.ADDEDGE"), - - GETEDGES("graph.GETEDGES"), - GETNODES("graph.GETNODES"), - - GETNODEEDGES("graph.GETNODEEDGES"), - GETNEIGHBOURS("graph.GETNEIGHBOURS"), - - REMOVEEDGE("graph.REMOVEEDGE"), - DELETEGRAPH("graph.DELETE"), - - QUERY("graph.QUERY"); - - private final byte[] raw; - - Command(String alt) { - raw = SafeEncoder.encode(alt); - } - - public byte[] getRaw() { - return raw; - } - } -} \ No newline at end of file diff --git a/src/main/java/com/redislabs/redisgraph/Record.java b/src/main/java/com/redislabs/redisgraph/Record.java new file mode 100644 index 0000000..f789f07 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/Record.java @@ -0,0 +1,56 @@ +package com.redislabs.redisgraph; + +import java.util.List; + +/** + * Container for RedisGraph result values. + * + * List records are returned from RedisGraph statement execution, contained within a ResultSet. + */ +public interface Record { + + /** + * The value at the given field index (represented as String) + * + * @param index + * @return + */ + String getString(int index); + + /** + * The value at the given field (represented as String) + * + * @param key + * @return + */ + String getString(String key); + + /** + * The keys of the record + * + * @return + */ + List keys(); + + /** + * The values of the record + * + * @return + */ + List values(); + + /** + * Check if the keys contain the given key + * + * @param key + * @return + */ + boolean containsKey(String key); + + /** + * The number of fields in this record + * + * @return + */ + int size(); +} diff --git a/src/main/java/com/redislabs/redisgraph/RedisEdge.java b/src/main/java/com/redislabs/redisgraph/RedisEdge.java deleted file mode 100644 index b9d024a..0000000 --- a/src/main/java/com/redislabs/redisgraph/RedisEdge.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.redislabs.redisgraph; - -import java.util.HashMap; - -public class RedisEdge { - private String id; - private String relation; - private HashMap attributes; - private RedisNode src; - private RedisNode dest; - - public RedisEdge(String id, RedisNode src, RedisNode dest, String relation, HashMap attributes) { - this.id = id; - this.relation = relation; - this.attributes = attributes; - this.src = src; - this.dest = dest; - } - - public String getId() { - return id; - } - - public String getRelation() { - return relation; - } - - public HashMap getAttributes() { - return attributes; - } - - public RedisNode getSrc() { - return src; - } - - public RedisNode getDest() { - return dest; - } -} diff --git a/src/main/java/com/redislabs/redisgraph/RedisGraphAPI.java b/src/main/java/com/redislabs/redisgraph/RedisGraphAPI.java index 53a67ad..3cc68e7 100644 --- a/src/main/java/com/redislabs/redisgraph/RedisGraphAPI.java +++ b/src/main/java/com/redislabs/redisgraph/RedisGraphAPI.java @@ -1,154 +1,67 @@ package com.redislabs.redisgraph; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.redislabs.redisgraph.impl.ResultSetImpl; +import redis.clients.jedis.BinaryClient; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.commands.ProtocolCommand; + +/** + * RedisGraph client + */ public class RedisGraphAPI { - Client client; - String graphId; + final private JedisPool client; + final private String graphId; + /** + * Creates a client to a specific graph running on the local machine + * + * @param graphId the graph id + */ public RedisGraphAPI(String graphId) { - this.graphId = graphId; - client = new Client("localhost", 6379); - } - - public RedisNode createNode(Object... attributes) { - String id = client.createNode(this.graphId, attributes); - - Map attr = new HashMap(); - - for(int i = 0; i < attributes.length; i+=2) { - String key = attributes[i].toString(); - String value = attributes[i+1].toString(); - attr.put(key, value); - } - - return new RedisNode(id, null, attr); - } - - public RedisNode createLabeledNode(String label, Object... attributes) { - String id = client.createNode(this.graphId, label, attributes); - - Map attr = new HashMap(); - - for(int i = 0; i < attributes.length; i+=2) { - String key = attributes[i].toString(); - String value = attributes[i+1].toString(); - attr.put(key, value); - } - - return new RedisNode(id, label, attr); - } - - public RedisNode getNode(String id) { - List node = getNodes(id); - if(node != null && node.size() == 1) { - return node.get(0); - } - return null; - } - - public List getNodes(Object... ids) { - List res = new ArrayList(); - List> nodes = client.getNodes(this.graphId, ids); - - if(nodes == null) { - return null; - } - - // Scan through raw results - for(HashMap nodeAttributs: nodes) { - - String id = nodeAttributs.get("id"); - nodeAttributs.remove("id"); - - String label = nodeAttributs.get("label"); - nodeAttributs.remove("label"); - - res.add(new RedisNode(id, label, nodeAttributs)); - } - - return res; + this(graphId, "localhost", 6379); } - - public RedisEdge getEdge(String id) { - List edge = getEdges(id); - if(edge != null && edge.size() == 1) { - return edge.get(0); - } - return null; - } - - public List getEdges(String... ids) { - List res = new ArrayList(); - List> edges = client.getEdges(this.graphId, ids); - - if(edges == null) { - return null; - } - - for(HashMap edgeAttributs: edges) { - String edgeId = edgeAttributs.get("id"); - String relation = edgeAttributs.get("label"); - String srcNodeId = edgeAttributs.get("src"); - String destNodeId = edgeAttributs.get("dest"); - - edgeAttributs.remove("id"); - edgeAttributs.remove("type"); - edgeAttributs.remove("src"); - edgeAttributs.remove("dest"); - edgeAttributs.remove("label"); - - List nodes = getNodes(srcNodeId, destNodeId); - RedisNode srcNode = nodes.get(0); - RedisNode destNode = nodes.get(1); - - res.add(new RedisEdge(edgeId, srcNode, destNode, relation, edgeAttributs)); - } - return res; - } - - public List getNodeEdges(String nodeId, String edgeType, int direction) { - List edgeIds = client.getNodeEdges(this.graphId, nodeId, edgeType, direction); - ArrayList edges = new ArrayList(); - - for(String id: edgeIds) { - edges.add(getEdge(id)); - } - - return edges; - } - - public List getNeighbours(String nodeId, String edgeType, int direction) { - List nodeIds = client.getNeighbours(this.graphId, nodeId, edgeType, direction); - return this.getNodes(nodeIds.toArray()); - } - - public RedisEdge connectNodes(RedisNode src, String relation, RedisNode dest, Object... attributes) { - String edgeId = client.connectNodes(this.graphId, src.getId(), relation, dest.getId(), attributes); - HashMap attr = new HashMap(); - - for(int i = 0; i < attributes.length; i+=2) { - String key = attributes[i].toString(); - String value = attributes[i+1].toString(); - attr.put(key, value); - } - - return new RedisEdge(edgeId, src, dest, relation, attr); + + /** + * Creates a client to a specific graph running on the specific host/post + * + * @param graphId the graph id + * @param host Redis host + * @param port Redis port + */ + public RedisGraphAPI(String graphId, String host, int port) { + this.graphId = graphId; + this.client = new JedisPool(host, port); } + /** + * Execute a Cypher query + * + * @param query Cypher query + * @return a result set + */ public ResultSet query(String query) { - return client.query(this.graphId, query); + try (Jedis conn = _conn()) { + return new ResultSetImpl(sendCommand(conn, Command.QUERY, graphId, query).getObjectMultiBulkReply()); + } } - public boolean setProperty(String elementId, String key, Object value) { - return client.setProperty(elementId, key, value); + /** + * Delete the Graph (Current implementation flush the all DB) + */ + public void deleteGraph() { + _conn().flushDB(); } - public void deleteGraph() { - client.deleteGraph(this.graphId); + private BinaryClient sendCommand(Jedis conn, ProtocolCommand provider, String ...args) { + BinaryClient client = conn.getClient(); + client.sendCommand(provider, args); + return client; + } + + private Jedis _conn() { + return this.client.getResource(); } } diff --git a/src/main/java/com/redislabs/redisgraph/RedisNode.java b/src/main/java/com/redislabs/redisgraph/RedisNode.java deleted file mode 100644 index 92aefbc..0000000 --- a/src/main/java/com/redislabs/redisgraph/RedisNode.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.redislabs.redisgraph; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class RedisNode { - private String id; - private String label; - private Map attributes; - - private List incomingEdges; - private List outgoingEdges; - - public RedisNode(String id, String label, Map attributes) { - this.id = id; - this.label = label; - this.attributes = attributes; - this.incomingEdges = new ArrayList(); - this.outgoingEdges = new ArrayList(); - } - - public String getId() { - return id; - } - - public String getLabel() { - return label; - } - - public Map getAttributes() { - return attributes; - } - - public List getIncomingEdges() { - return incomingEdges; - } - - public List getOutgoingEdges() { - return outgoingEdges; - } -} diff --git a/src/main/java/com/redislabs/redisgraph/ResultSet.java b/src/main/java/com/redislabs/redisgraph/ResultSet.java index 07ede04..6eca445 100644 --- a/src/main/java/com/redislabs/redisgraph/ResultSet.java +++ b/src/main/java/com/redislabs/redisgraph/ResultSet.java @@ -1,31 +1,14 @@ package com.redislabs.redisgraph; -import java.util.ArrayList; -import java.util.List; - -public class ResultSet { - public int totalResults; - public String[] header; - public List results; - - public ResultSet(List resp) { - - // Empty result set - if(resp.size() == 0) { - totalResults = 0; - results = new ArrayList(0); - } - - // First row is a header row - String header_row = new String((byte[]) resp.get(0)); - header = header_row.split(","); - totalResults = resp.size()-2; - results = new ArrayList(totalResults); - - // Skips last row (runtime info) - for (int i = 1; i < resp.size()-1; i++) { - String row = new String((byte[]) resp.get(i)); - results.add(row.split(",")); - } - } +import java.util.Iterator; + +/** + * Hold a query result + */ +public interface ResultSet extends Iterator{ + /** + * Return the query statistics + * @return statistics object + */ + Statistics getStatistics(); } diff --git a/src/main/java/com/redislabs/redisgraph/Statistics.java b/src/main/java/com/redislabs/redisgraph/Statistics.java new file mode 100644 index 0000000..f62f19f --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/Statistics.java @@ -0,0 +1,62 @@ +package com.redislabs.redisgraph; + + +public interface Statistics { + + /** + * Different Statistics labels + */ + enum Label{ + LABELS_ADDED("Labels added"), + NODES_CREATED("Nodes created"), + NODES_DELETED("Nodes deleted"), + RELATIONSHIPS_DELETED("Relationships deleted"), + PROPERTIES_SET("Properties set"), + RELATIONSHIPS_CREATED("Relationships created"), + QUERY_INTERNAL_EXECUTION_TIME("Query internal execution time"); + + private final String text; + + Label(String text) { + this.text = text; + } + + @Override + public String toString() { + return this.text; + } + + /** + * Get a Label by label text + * + * @param value label text + * @return the matching Label + */ + public static Label getEnum(String value) { + for(Label v : values()) { + if(v.toString().equalsIgnoreCase(value)) return v; + } + throw new IllegalArgumentException(); + } + } + + /** + * Retrieves the relevant statistic + * + * @param label the requested statistic label + * @return a String representation of the specific statistic or null + */ + String getStringValue(Statistics.Label label); + + int nodesCreated(); + + int nodesDeleted(); + + int labelsAdded(); + + int relationshipsDeleted(); + + int relationshipsCreated(); + + int propertiesSet(); +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/RecordImpl.java b/src/main/java/com/redislabs/redisgraph/impl/RecordImpl.java new file mode 100644 index 0000000..eabc94a --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/RecordImpl.java @@ -0,0 +1,47 @@ +package com.redislabs.redisgraph.impl; + +import java.util.List; + +import com.redislabs.redisgraph.Record; + +public class RecordImpl implements Record { + + final private List header; + final private List values; + + RecordImpl(List header, List values){ + this.header=header; + this.values = values; + } + + @Override + public String getString(int index) { + return this.values.get(index); + } + + @Override + public String getString(String key) { + return getString(this.header.indexOf(key)); + } + + @Override + public List keys() { + return header; + } + + @Override + public List values() { + return this.values; + } + + @Override + public boolean containsKey(String key) { + return this.header.contains(key); + } + + @Override + public int size() { + return this.header.size(); + } + +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/ResultSetImpl.java b/src/main/java/com/redislabs/redisgraph/impl/ResultSetImpl.java new file mode 100644 index 0000000..5704424 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/ResultSetImpl.java @@ -0,0 +1,66 @@ +package com.redislabs.redisgraph.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.redislabs.redisgraph.Record; +import com.redislabs.redisgraph.ResultSet; +import com.redislabs.redisgraph.Statistics; + +import redis.clients.jedis.util.SafeEncoder; + +public class ResultSetImpl implements ResultSet{ + + final private int totalResults; + final private List header; + final private List results; + final private Statistics statistics; + private int position = 0; + + public ResultSetImpl(List resp) { + + this.statistics = new StatisticsImpl((List)resp.get(1)); + + ArrayList> result = (ArrayList>) resp.get(0); + + // Empty result set + if(result == null || result.size() == 0) { + header = new ArrayList<>(0); + totalResults = 0; + results = new ArrayList(0); + } else { + ArrayList headers = result.get(0); + header = headers.stream().map( h -> new String(h)).collect(Collectors.toList()); + + // First row is a header row + totalResults = result.size()-1; + results = new ArrayList(totalResults); + // Skips last row (runtime info) + for (int i = 1; i <= totalResults; i++) { + ArrayList row = result.get(i); + Record record = new RecordImpl(header, row.stream().map( h -> SafeEncoder.encode(h)).collect(Collectors.toList())); + results.add(record); + } + } + } + + public List getHeader(){ + return header; + } + + @Override + public boolean hasNext() { + return position < results.size(); + } + + @Override + public Record next() { + return results.get(position++); + } + + @Override + public Statistics getStatistics() { + return statistics; + } +} diff --git a/src/main/java/com/redislabs/redisgraph/impl/StatisticsImpl.java b/src/main/java/com/redislabs/redisgraph/impl/StatisticsImpl.java new file mode 100644 index 0000000..984ab28 --- /dev/null +++ b/src/main/java/com/redislabs/redisgraph/impl/StatisticsImpl.java @@ -0,0 +1,71 @@ +package com.redislabs.redisgraph.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.redislabs.redisgraph.Statistics; + +import redis.clients.jedis.util.SafeEncoder; + +public class StatisticsImpl implements Statistics { + final private List raw; + final private Map statistics; + + StatisticsImpl(List raw){ + this.raw = raw; + this.statistics = new HashMap(raw.size()); // lazy loaded + } + + @Override + public String getStringValue(Statistics.Label label) { + return getStatistics().get(label); + } + + private Map getStatistics(){ + if(statistics.size() == 0) { + for(byte[] touple : this.raw) { + String row = SafeEncoder.encode(touple); + String[] rowTouple = row.split(":"); + this.statistics.put( Statistics.Label.getEnum(rowTouple[0]), rowTouple[1].trim()); + } + } + return statistics; + } + + public int getIntValue(Statistics.Label label) { + String value = getStringValue(label); + return value==null ? 0 : Integer.parseInt(value); + } + + @Override + public int nodesCreated() { + return getIntValue(Label.NODES_CREATED); + } + + @Override + public int nodesDeleted() { + return getIntValue(Label.NODES_DELETED); + } + + @Override + public int labelsAdded() { + return getIntValue(Label.LABELS_ADDED); + } + + @Override + public int relationshipsDeleted() { + return getIntValue(Label.RELATIONSHIPS_DELETED); + } + + @Override + public int relationshipsCreated() { + return getIntValue(Label.RELATIONSHIPS_CREATED); + } + + @Override + public int propertiesSet() { + return getIntValue(Label.PROPERTIES_SET); + } +} diff --git a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java index 9dabf78..b48d902 100644 --- a/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java +++ b/src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java @@ -1,9 +1,10 @@ package com.redislabs.redisgraph; + import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import com.redislabs.redisgraph.Statistics.Label; public class RedisGraphAPITest { RedisGraphAPI api; @@ -12,247 +13,77 @@ public RedisGraphAPITest() { api = new RedisGraphAPI("social"); } - @org.testng.annotations.BeforeSuite - @org.testng.annotations.BeforeMethod + @Before public void flushDB() { - api.deleteGraph(); + api.deleteGraph(); } - @org.testng.annotations.Test + + @Test public void testCreateNode() throws Exception { - // Create a node - RedisNode node = api.createNode("name", "roi", "age", 32); - - // Validate node - Assert.assertNotNull(node.getId()); - Assert.assertSame(node.getAttributes().get("name"), "roi"); - Assert.assertSame(Integer.parseInt(node.getAttributes().get("age")), 32); - Assert.assertSame(node.getAttributes().size(),2); + // Create a node + ResultSet result = api.query("CREATE ({name:\"roi\",age:32})"); + Assert.assertFalse(result.hasNext()); + + Assert.assertEquals(1, result.getStatistics().nodesCreated()); + Assert.assertNull(result.getStatistics().getStringValue(Label.NODES_DELETED)); + Assert.assertNull(result.getStatistics().getStringValue(Label.RELATIONSHIPS_CREATED)); + Assert.assertNull(result.getStatistics().getStringValue(Label.RELATIONSHIPS_DELETED)); + Assert.assertEquals(2, result.getStatistics().propertiesSet()); + Assert.assertNotNull(result.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); } - @org.testng.annotations.Test - public void testCreateLabeledNode() throws Exception { + @Test + public void testCreateLabeledNode() throws Exception { // Create a node with a label - RedisNode node = api.createLabeledNode("human","name", "roi", "age", 32); - - // Validate node - Assert.assertNotNull(node.getId()); - Assert.assertSame(node.getLabel(), "human"); - Assert.assertSame(node.getAttributes().get("name"), "roi"); - Assert.assertSame(Integer.parseInt(node.getAttributes().get("age")), 32); - Assert.assertSame(node.getAttributes().size(),2); + ResultSet result = api.query("CREATE (:human{name:\"danny\",age:12})"); + Assert.assertFalse(result.hasNext()); + + Assert.assertEquals("1", result.getStatistics().getStringValue(Label.NODES_CREATED)); + Assert.assertEquals("2", result.getStatistics().getStringValue(Label.PROPERTIES_SET)); + Assert.assertNotNull(result.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); } - @org.testng.annotations.Test + @Test public void testConnectNodes() throws Exception { // Create both source and destination nodes - RedisNode src = api.createNode("name", "roi", "age", 32); - RedisNode dest = api.createNode("name", "amit", "age", 30); - - // Connect source and destination nodes. - RedisEdge edge = api.connectNodes(src, "knows", dest, "strength", "3", "from", "high-school"); - - // Validate edge - Assert.assertNotNull(edge.getId()); - Assert.assertEquals(edge.getRelation(), "knows"); - Assert.assertSame(edge.getAttributes().size(), 2); - Assert.assertSame(edge.getAttributes().get("strength"), "3"); - Assert.assertSame(edge.getAttributes().get("from"), "high-school"); - Assert.assertSame(edge.getSrc(), src); - Assert.assertSame(edge.getDest(), dest); + ResultSet createResult1 = api.query("CREATE (:person{name:'roi',age:32})"); + ResultSet createResult2 = api.query("CREATE (:person{name:'amit',age:30})"); + + // Connect source and destination nodes. + ResultSet matchResult = api.query("MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[knows]->(a)"); + + Assert.assertFalse(matchResult.hasNext()); + Assert.assertNull(matchResult.getStatistics().getStringValue(Label.NODES_CREATED)); + Assert.assertNull(matchResult.getStatistics().getStringValue(Label.PROPERTIES_SET)); + Assert.assertEquals(1, matchResult.getStatistics().relationshipsCreated()); + Assert.assertEquals(0, matchResult.getStatistics().relationshipsDeleted()); + Assert.assertNotNull(matchResult.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); } - @org.testng.annotations.Test + @Test public void testQuery() throws Exception { - // Create both source and destination nodes - RedisNode src = api.createLabeledNode("qhuman","name", "roi", "age", 32); - RedisNode dest = api.createLabeledNode("qhuman","name", "amit", "age", 30); - - // Connect source and destination nodes. - api.connectNodes(src, "knows", dest, "strength", "3", "from", "high-school"); + + // Create both source and destination nodes + ResultSet create1Result = api.query("CREATE (:qhuman{name:'roi',age:32})"); + ResultSet create2Result = api.query("CREATE (:qhuman{name:'amit',age:30})"); + + // Connect source and destination nodes. + ResultSet connectResult= api.query("MATCH (a:qhuman), (b:qhuman) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[knows]->(b)"); // Query - ResultSet resultSet = api.query("MATCH (a:qhuman)-[]->(:qhuman) RETURN a"); - - // Expecting a single result - Assert.assertEquals(resultSet.totalResults, 1); - Assert.assertEquals(resultSet.results.size(), resultSet.totalResults); - Assert.assertEquals(resultSet.results.get(0)[0], "roi"); - Assert.assertEquals(resultSet.results.get(0)[1], "32"); - } - - @org.testng.annotations.Test - public void testGetNodes() throws Exception { - RedisGraphAPI api = new RedisGraphAPI("social"); - - // Create nodes - HashMap expected = new HashMap(3); - expected.put("roi", api.createLabeledNode("human", "name", "roi", "age", 32)); - expected.put("amit", api.createLabeledNode("human", "name", "amit", "age", 30)); - expected.put("shany", api.createLabeledNode("human", "name", "shany", "age", 23)); - - // Get all three nodes - List retrievedNodes = api.getNodes(); - - // Expecting a single result - Assert.assertNotNull(retrievedNodes); - Assert.assertEquals(retrievedNodes.size(), expected.size()); - - for(RedisNode actualNode: retrievedNodes) { - RedisNode expectedNode = expected.get(actualNode.getAttributes().get("name")); - Assert.assertNotNull(expectedNode); - - Assert.assertEquals(actualNode.getId(), expectedNode.getId()); - Assert.assertEquals(actualNode.getLabel(), expectedNode.getLabel()); - Assert.assertEquals(actualNode.getAttributes().size(), 2); - Assert.assertEquals(Integer.parseInt(expectedNode.getAttributes().get("age")), Integer.parseInt(actualNode.getAttributes().get("age"))); - } - - // List of node ids created. - List ids = new ArrayList(expected.size()); - for (RedisNode n: expected.values()) { - ids.add(n.getId()); - } - - retrievedNodes = api.getNodes(ids.toArray()); - for(RedisNode actualNode: retrievedNodes) { - RedisNode expectedNode = expected.get(actualNode.getAttributes().get("name")); - Assert.assertNotNull(expectedNode); - - Assert.assertEquals(actualNode.getId(), expectedNode.getId()); - Assert.assertEquals(actualNode.getLabel(), expectedNode.getLabel()); - Assert.assertEquals(actualNode.getAttributes().size(), 2); - Assert.assertEquals(Integer.parseInt(expectedNode.getAttributes().get("age")), Integer.parseInt(actualNode.getAttributes().get("age"))); - } - } - - @org.testng.annotations.Test - public void testGetEdge() throws Exception { - // Create both source and destination nodes - RedisNode src = api.createLabeledNode("human","name", "roi", "age", 32); - RedisNode dest = api.createLabeledNode("human","name", "amit", "age", 30); - - // Connect source and destination nodes. - RedisEdge edge = api.connectNodes(src, "knows", dest, "strength", "3", "from", "high-school"); - - // Get edge - RedisEdge retrievedEdge = api.getEdge(edge.getId()); - - // Expecting a single result - Assert.assertNotNull(retrievedEdge); - Assert.assertEquals(edge.getId(), retrievedEdge.getId()); - Assert.assertEquals(edge.getRelation(), retrievedEdge.getRelation()); - Assert.assertEquals(retrievedEdge.getAttributes().size(), 2); - Assert.assertEquals(retrievedEdge.getAttributes().get("strength"), "3"); - Assert.assertEquals(retrievedEdge.getAttributes().get("from"), "high-school"); - - Assert.assertEquals(retrievedEdge.getSrc().getId(), src.getId()); - Assert.assertEquals(retrievedEdge.getDest().getId(), dest.getId()); - } - - @org.testng.annotations.Test - public void testSetProperty() throws Exception { - RedisGraphAPI api = new RedisGraphAPI("social"); - - // Create a node - RedisNode node = api.createNode("name", "shimshon", "age", 60); - api.setProperty(node.getId(), "age", 61); - - node = api.getNode(node.getId()); - - // Validate node - Assert.assertSame(Integer.parseInt(node.getAttributes().get("age")), 61); - } - - @org.testng.annotations.Test - public void testGraphDelete() throws Exception { - RedisGraphAPI api = new RedisGraphAPI("social"); - RedisNode roi = api.createNode("name", "roi", "age", 32); - RedisNode amit = api.createNode("name", "amit", "age", 30); - - // Connect source and destination nodes. - RedisEdge edge = api.connectNodes(roi, "knows", amit); - - api.deleteGraph(); - - roi = api.getNode(roi.getId()); - Assert.assertNull(roi); - - edge = api.getEdge(edge.getId()); - Assert.assertNull(edge); - } - - @org.testng.annotations.Test - public void testGetNodeEdges() throws Exception { - // Create both source and destination nodes - RedisNode roi = api.createNode("name", "roi", "age", 32); - RedisNode amit = api.createNode("name", "amit", "age", 30); - RedisNode shany = api.createNode("name", "shany", "age", 23); - - // Connect source and destination nodes. - api.connectNodes(roi, "knows", amit); - api.connectNodes(roi, "knows", shany); - api.connectNodes(amit, "knows", roi); - api.connectNodes(shany, "knows", roi); - - int DIR_OUT = 0; - int DIR_IN = 1; - int DIR_BOTH = 2; - - List edges; - edges = api.getNodeEdges(roi.getId(), "knows", DIR_OUT); - Assert.assertEquals(edges.size(), 2); - - edges = api.getNodeEdges(roi.getId(), "knows", DIR_IN); - Assert.assertEquals(edges.size(), 2); - - edges = api.getNodeEdges(roi.getId(), "knows", DIR_BOTH); - Assert.assertEquals(edges.size(), 4); - - edges = api.getNodeEdges(amit.getId(), "knows", DIR_OUT); - Assert.assertEquals(edges.size(), 1); - - edges = api.getNodeEdges(amit.getId(), "knows", DIR_IN); - Assert.assertEquals(edges.size(), 1); - - edges = api.getNodeEdges(amit.getId(), "knows", DIR_BOTH); - Assert.assertEquals(edges.size(), 2); - } - - @org.testng.annotations.Test - public void testGetNeighbours() throws Exception { - // Create both source and destination nodes - RedisNode roi = api.createNode("name", "roi", "age", 32); - RedisNode amit = api.createNode("name", "amit", "age", 30); - RedisNode shany = api.createNode("name", "shany", "age", 23); - - // Connect source and destination nodes. - api.connectNodes(roi, "knows", amit); - api.connectNodes(roi, "knows", shany); - api.connectNodes(amit, "knows", roi); - api.connectNodes(shany, "knows", roi); - - int DIR_OUT = 0; - int DIR_IN = 1; - int DIR_BOTH = 2; - - List neighbours; - neighbours = api.getNeighbours(roi.getId(), "knows", DIR_OUT); - Assert.assertEquals(neighbours.size(), 2); - - neighbours = api.getNeighbours(roi.getId(), "knows", DIR_IN); - Assert.assertEquals(neighbours.size(), 2); - - neighbours = api.getNeighbours(roi.getId(), "knows", DIR_BOTH); - Assert.assertEquals(neighbours.size(), 4); - - neighbours = api.getNeighbours(amit.getId(), "knows", DIR_OUT); - Assert.assertEquals(neighbours.size(), 1); - - neighbours = api.getNeighbours(amit.getId(), "knows", DIR_IN); - Assert.assertEquals(neighbours.size(), 1); - - neighbours = api.getNeighbours(amit.getId(), "knows", DIR_BOTH); - Assert.assertEquals(neighbours.size(), 2); + ResultSet resultSet = api.query("MATCH (a:qhuman)-[knows]->(:qhuman) RETURN a"); + + Assert.assertTrue(resultSet.hasNext()); + Assert.assertEquals(0, resultSet.getStatistics().nodesCreated()); + Assert.assertEquals(0, resultSet.getStatistics().propertiesSet()); + Assert.assertEquals(0, resultSet.getStatistics().relationshipsCreated()); + Assert.assertEquals(0, resultSet.getStatistics().relationshipsDeleted()); + Assert.assertNotNull(resultSet.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME)); + + Record record = resultSet.next(); + Assert.assertEquals( "roi", record.getString(1)); + Assert.assertEquals( "32.000000", record.getString(0)); + } } \ No newline at end of file