diff --git a/README.md b/README.md index 39c5b77..ce45f25 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ RedisGraph python client ```python import redis -from redisgraph import Node, Edge, Graph +from redisgraph import Node, Edge, Graph, Path r = redis.Redis(host='localhost', port=6379) @@ -47,6 +47,15 @@ for record in result.result_set: person_age = record[1] visit_purpose = record[2] country_name = record[3] + +query = """MATCH p = (:person)-[:visited {purpose:"pleasure"}]->(:country) RETURN p""" + +result = redis_graph.query(query) + +# Iterate through resultset +for record in result.result_set: + path = record[0] + print(path) # All done, remove graph. diff --git a/redisgraph/__init__.py b/redisgraph/__init__.py index adc7377..0b06119 100644 --- a/redisgraph/__init__.py +++ b/redisgraph/__init__.py @@ -1,3 +1,4 @@ from .node import Node from .edge import Edge from .graph import Graph +from .path import Path diff --git a/redisgraph/path.py b/redisgraph/path.py new file mode 100644 index 0000000..d3008ec --- /dev/null +++ b/redisgraph/path.py @@ -0,0 +1,67 @@ +from .node import Node +from .edge import Edge + +class Path(object): + + def __init__(self, nodes, edges): + assert(isinstance(nodes, list) and isinstance(edges, list)) + self.nodes = nodes + self.edges = edges + self.append_type = Node + + @classmethod + def new_empty_path(cls): + return cls([], []) + + def nodes(self): + return self.nodes + + def edges(self): + return self.edges + + def get_node(self, index): + return self.nodes[index] + + def get_relationship(self, index): + return self.edges[index] + + def first_node(self): + return self.nodes[0] + + def last_node(self): + return self.nodes[-1] + + def edge_count(self): + return len(self.edges) + + def nodes_count(self): + return len(self.nodes) + + def add_node(self, node): + assert(type(node) == self.append_type) + self.nodes.append(node) + self.append_type = Edge + return self + + def add_edge(self, edge): + assert(type(edge) == self.append_type) + self.edges.append(edge) + self.append_type = Node + return self + + def __eq__(self, other): + return self.nodes == other.nodes and self.edges == other.edges + + def __str__(self): + res = "<" + edge_count = self.edge_count() + for i in range(0, edge_count): + node_id = self.get_node(i).id + res += "(" + str(node_id) + ")" + edge = self.get_relationship(i) + res += "-[" + str(int(edge.id)) + "]->" if edge.src_node == node_id else "<-[" + str(int(edge.id)) + "]-" + node_id = self.get_node(edge_count).id + res += "(" + str(node_id) + ")" + res += ">" + return res + \ No newline at end of file diff --git a/redisgraph/query_result.py b/redisgraph/query_result.py index 2f437bf..2c8b479 100644 --- a/redisgraph/query_result.py +++ b/redisgraph/query_result.py @@ -1,5 +1,6 @@ from .node import Node from .edge import Edge +from .path import Path from prettytable import PrettyTable from redis import ResponseError @@ -21,6 +22,7 @@ class ResultSetScalarTypes(object): VALUE_ARRAY = 6 VALUE_EDGE = 7 VALUE_NODE = 8 + VALUE_PATH = 9 class QueryResult(object): LABELS_ADDED = 'Labels added' @@ -124,6 +126,11 @@ def parse_edge(self, cell): properties = self.parse_entity_properties(cell[4]) return Edge(src_node_id, relation, dest_node_id, edge_id=edge_id, properties=properties) + def parse_path(self, cell): + nodes = self.parse_scalar(cell[0]) + edges = self.parse_scalar(cell[1]) + return Path(nodes, edges) + def parse_scalar(self, cell): scalar_type = int(cell[0]) value = cell[1] @@ -162,6 +169,9 @@ def parse_scalar(self, cell): elif scalar_type == ResultSetScalarTypes.VALUE_EDGE: scalar = self.parse_edge(value) + elif scalar_type == ResultSetScalarTypes.VALUE_PATH: + scalar = self.parse_path(value) + elif scalar_type == ResultSetScalarTypes.VALUE_UNKNOWN: print("Unknown scalar type\n") diff --git a/setup.py b/setup.py index 136b36d..1885543 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup, find_packages setup( name='redisgraph', - version='2.0', + version='2.1', description='RedisGraph Python Client', url='https://github.com/redislabs/redisgraph-py', diff --git a/test.py b/test.py index 31f677f..9a372f2 100644 --- a/test.py +++ b/test.py @@ -65,5 +65,35 @@ def test_array_functions(self): # All done, remove graph. redis_graph.delete() + + def test_path(self): + redis_graph = Graph('social', self.r) + + node0 = Node(node_id=0, label="L1") + node1 = Node(node_id=1, label="L1") + node2 = Node(node_id=2, label="L1") + edge01 = Edge(node0, "R1", node1, edge_id=0, properties={'value': 1}) + edge12 = Edge(node1, "R1", node2, edge_id=1, properties={'value': 2}) + + redis_graph.add_node(node0) + redis_graph.add_node(node1) + redis_graph.add_node(node2) + redis_graph.add_edge(edge01) + redis_graph.add_edge(edge12) + + redis_graph.flush() + + path01 = Path.new_empty_path().add_node(node0).add_edge(edge01).add_node(node1) + path12 = Path.new_empty_path().add_node(node1).add_edge(edge12).add_node(node2) + expected_results = [[path01], [path12]] + + query = "MATCH p=(:L1)-[:R1]->(:L1) RETURN p" + result = redis_graph.query(query) + self.assertEqual(expected_results, result.result_set) + + # All done, remove graph. + redis_graph.delete() + + if __name__ == '__main__': unittest.main()