def test_modify_node(self): """ Tests L{QueryEvaluator.modify_node} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label' : 'Person', 'Name' : 'Alice'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob'} attrs3 = {'Label' : 'Person', 'Name' : 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type' : 'friend'} edge_attrs2 = {'rel_type' : 'friend', 'fam' : 'cousin'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) # Tests adding attributes to node q.modify_node(attrs1, {'Age' : '10'}, True) match_lst1 = q.match_node(attrs1) result1 = [(node1[0], {'Label' : 'Person', 'Name' : 'Alice', 'Age' : '10'})] self.assertEqual(match_lst1, result1) # Tests removing attributes to node q.modify_node(attrs1, {'Age' : '10'}, False) match_lst2 = q.match_node(attrs1) result2 = [(node1[0], attrs1)] self.assertEqual(match_lst2, result2)
def test_match_node_project_node(self): """ Tests applying a project to a simple match node query for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) proj = Project() attrs1 = {'Label' : 'Person', 'Name' : 'Alice', 'Salary' : '500'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob', 'Salary' : '1000'} attrs3 = {'Label' : 'Person', 'Name' : 'John', 'Salary' : '20000'} attrs4 = {'Label' : 'Person', 'Name' : 'Donnie', 'Salary' : '100000000'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) node4 = q.add_node(attrs4) # Test matching all nodes and then projecting to a single attribute. match_lst1 = q.match_node({'Label' : 'Person'}) # Project on salary field. filtered_lst1 = proj.project(match_lst1, ['Salary']) self.assertEqual(filtered_lst1, [{'Salary' : '500'}, {'Salary' : '1000'}, {'Salary' : '20000'}, {'Salary' : '100000000'}]) # Test matching a single node and then projecting to a single attribute. match_lst2 = q.match_node({'Name' : 'Alice'}) filtered_lst2 = proj.project(match_lst2, ['Salary']) self.assertEqual(filtered_lst2, [{'Salary' : '500'}])
def test_modify_rel(self): """ Test L{QueryEvaluator.modify_rel} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label' : 'Person', 'Name' : 'Alice'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob'} attrs3 = {'Label' : 'Person', 'Name' : 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type' : 'friend'} edge_attrs2 = {'rel_type' : 'friend', 'fam' : 'cousin'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) # Tests adding attributes to relationship q.modify_rel(edge_attrs2, {'like' : 'no'}, True) match_lst1 = q.match_rel(edge_attrs2) result1 = [(node2[0], node3[0], {'rel_type' : 'friend', 'fam' : 'cousin', 'like' : 'no'})] self.assertEqual(sorted(match_lst1), sorted(result1)) # Tests deleting attributes to relationship q.modify_rel(edge_attrs2, {'like' : 'no'}, False) match_lst2 = q.match_rel(edge_attrs2) result2 = [(node2[0], node3[0], edge_attrs2)] self.assertEqual(sorted(match_lst2), sorted(result2))
def test_delete_rel(self): """ Tests L{QueryEvaluator.delete_rel} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label' : 'Person', 'Name' : 'Alice'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob'} attrs3 = {'Label' : 'Person', 'Name' : 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type' : 'friend'} edge_attrs2 = {'rel_type' : 'friend', 'fam' : 'cousin'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) # Tests deleting no relationship q.delete_rel({'rel_type' : 'friend', 'fam' : 'dad'}) match_lst1 = q.match({}, {}, {}) result1 = [(node1[0], node2[0], edge_attrs1), (node2[0], node3[0], edge_attrs2)] self.assertEqual(match_lst1, result1) # Tests deleting relationship q.delete_rel(edge_attrs1) match_lst2 = q.match({}, {}, {}) result2 = [] self.assertEqual(match_lst2, result2)
def test_match_node_rel(self): """ Tests L{QueryEvaluator.match_node_rel} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label': 'Person', 'Name': 'Alice'} attrs2 = {'Label': 'Person', 'Name': 'Bob'} attrs3 = {'Label': 'Person', 'Name': 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type': 'friend'} edge_attrs2 = {'rel_type': 'friend', 'fam': 'cousin'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) edge3 = q.add_relationship(node2, node1, edge_attrs1) # Test matching with no results match_lst1 = q.match_node_rel(node1[1], edge_attrs2) result1 = [] self.assertEqual(match_lst1, result1) # Test matching with single result match_lst2 = q.match_node_rel(node2[1], edge_attrs2) result2 = [(node2[0], node3[0], edge_attrs2)] self.assertEqual(match_lst2, result2) # Test matching with multiple result match_lst3 = q.match_node_rel(node2[1], {'rel_type': 'friend'}) result3 = [(node2[0], node1[0], edge_attrs1), (node2[0], node3[0], edge_attrs2)] self.assertEqual(match_lst3, result3)
def test_match_node_rel(self): """ Tests L{QueryEvaluator.match_node_rel} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label' : 'Person', 'Name' : 'Alice'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob'} attrs3 = {'Label' : 'Person', 'Name' : 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type' : 'friend'} edge_attrs2 = {'rel_type' : 'friend', 'fam' : 'cousin'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) edge3 = q.add_relationship(node2, node1, edge_attrs1) # Test matching with no results match_lst1 = q.match_node_rel(node1[1], edge_attrs2) result1 = [] self.assertEqual(match_lst1, result1) # Test matching with single result match_lst2 = q.match_node_rel(node2[1], edge_attrs2) result2 = [(node2[0], node3[0], edge_attrs2)] self.assertEqual(match_lst2, result2) # Test matching with multiple result match_lst3 = q.match_node_rel(node2[1], {'rel_type' : 'friend'}) result3 = [(node2[0], node1[0], edge_attrs1), (node2[0], node3[0], edge_attrs2)] self.assertEqual(match_lst3, result3)
def __init__(self, gs): """ Takes a L{GraphStructure} object to load the data into. @type gs: L{GraphStructure} object @param gs: L{GraphStructure} object that is used to store nodes and edges in. """ self.gs = gs self.gstorage = GraphStorage(self.gs) # Loads data on disk self.graph_file = 'graph_file' self.id_file = 'id_file' self.load_data() # Sets up a QueryEvaluator object to perform the loading operations self.q_eval = QueryEvaluator(gs)
def test_match_node(self): """ Tests L{QueryEvaluator.match_node} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label' : 'Person', 'Name' : 'Alice'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob'} attrs3 = {'Label' : 'Person', 'Name' : 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) # Test matching all node match_lst1 = q.match_node({'Label' : 'Person'}) self.assertEqual(match_lst1, [node1, node2, node3]) # Test matching single node match_lst2 = q.match_node({'Name' : 'Alice'}) self.assertEqual(match_lst2, [node1])
def __init__(self, object_list, gs): """ This class is the linker for microDB. It takes in a list of L{Command_Struct} objects that is generated by the parser, and a L{GraphStructure} object. @type object_list: List of L{Command_Struct} objects @param object_list: List of packaged commands that should be generated by the parser. @type: gs: L{GraphStructure} object @param gs: The current internal graph representation. """ self.list_objects = object_list self.gs = gs self.query_evaluator = QueryEvaluator(gs) self.pred = Predicates(gs)
def test_add_relationship(self): """ Tests L{QueryEvaluator.add_relationship} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label' : 'Person', 'Name' : 'Alice'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob'} attrs3 = {'Label' : 'Person', 'Name' : 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type' : 'friend'} edge_attrs2 = {'rel_type' : 'cousin'} # Test first edge edge1 = q.add_relationship(node1, node2, edge_attrs1) self.assertEqual(edge1, (node1[0], node2[0], edge_attrs1)) # Test second edge edge2 = q.add_relationship(node2, node3, edge_attrs2) self.assertEqual(edge2, (node2[0], node3[0], edge_attrs2))
def test_add_node(self): """ Tests L{QueryEvaluator.add_node} method of L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label' : 'Person', 'Name' : 'You'} attrs2 = {'Label' : 'Person', 'Name' : 'Me'} attrs3 = {'Label' : 'Person', 'Name' : 'She', 'Age' : 23} # Test first node node1 = q.add_node(attrs1) self.assertEqual(node1[0], 1) self.assertEqual(node1[1], attrs1) # Test second node node2 = q.add_node(attrs2) self.assertEqual(node2[0], 2) self.assertEqual(node2[1], attrs2) # Test third node node3 = q.add_node(attrs3) self.assertEqual(node3[0], 3) self.assertEqual(node3[1], attrs3)
def test_add_node(self): """ Tests L{QueryEvaluator.add_node} method of L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label': 'Person', 'Name': 'You'} attrs2 = {'Label': 'Person', 'Name': 'Me'} attrs3 = {'Label': 'Person', 'Name': 'She', 'Age': 23} # Test first node node1 = q.add_node(attrs1) self.assertEqual(node1[0], 1) self.assertEqual(node1[1], attrs1) # Test second node node2 = q.add_node(attrs2) self.assertEqual(node2[0], 2) self.assertEqual(node2[1], attrs2) # Test third node node3 = q.add_node(attrs3) self.assertEqual(node3[0], 3) self.assertEqual(node3[1], attrs3)
def test_match_node_project_node(self): """ Tests applying a project to a simple match node query for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) proj = Project() attrs1 = {'Label': 'Person', 'Name': 'Alice', 'Salary': '500'} attrs2 = {'Label': 'Person', 'Name': 'Bob', 'Salary': '1000'} attrs3 = {'Label': 'Person', 'Name': 'John', 'Salary': '20000'} attrs4 = {'Label': 'Person', 'Name': 'Donnie', 'Salary': '100000000'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) node4 = q.add_node(attrs4) # Test matching all nodes and then projecting to a single attribute. match_lst1 = q.match_node({'Label': 'Person'}) # Project on salary field. filtered_lst1 = proj.project(match_lst1, ['Salary']) self.assertEqual(filtered_lst1, [{ 'Salary': '500' }, { 'Salary': '1000' }, { 'Salary': '20000' }, { 'Salary': '100000000' }]) # Test matching a single node and then projecting to a single attribute. match_lst2 = q.match_node({'Name': 'Alice'}) filtered_lst2 = proj.project(match_lst2, ['Salary']) self.assertEqual(filtered_lst2, [{'Salary': '500'}])
def test_multi_match(self): """ Test L{QueryEvaluator.multi_match} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label' : 'Person', 'Name' : 'Alice'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob'} attrs3 = {'Label' : 'Person', 'Name' : 'John'} attrs4 = {'Label' : 'Person', 'Name' : 'Rick'} attrs5 = {'Label' : 'Person', 'Name' : 'Cat'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) node4 = q.add_node(attrs4) node5 = q.add_node(attrs5) edge_attrs1 = {'rel_type' : 'friend'} edge_attrs2 = {'rel_type' : 'friend', 'fam' : 'cousin'} edge_attrs3 = {'rel_type' : 'dad'} edge_attrs4 = {'rel_type' : 'mom'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) edge3 = q.add_relationship(node3, node4, edge_attrs3) edge4 = q.add_relationship(node4, node5, edge_attrs4) # Test no match for multiple length query result1 = q.multi_match([attrs1, attrs2, attrs3], [edge_attrs3, edge_attrs1]) self.assertEqual(result1, None) # Test single match for multiple length query result2 = q.multi_match([attrs1, attrs2, attrs3], [edge_attrs1, edge_attrs2]) self.assertEqual(result2, [(1, 3)]) # Tests many matches for multiple length query result3 = q.multi_match([{'Label' : 'Person'}, {'Label' : 'Person'}], [edge_attrs1]) self.assertEqual(result3, [edge1, edge2]) # Test all matches for multiple length query result4 = q.multi_match([{}, {}], [{}]) self.assertEqual(result4, [edge1, edge2, edge3, edge4])
def test_match_node_predicate(self): """ Tests applying a predicate to a simple match node query for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) pred = Predicates(gs) attrs1 = {'Label' : 'Person', 'Name' : 'Alice', 'Salary' : '500'} attrs2 = {'Label' : 'Person', 'Name' : 'Bob', 'Salary' : '1000'} attrs3 = {'Label' : 'Person', 'Name' : 'John', 'Salary' : '20000'} attrs4 = {'Label' : 'Person', 'Name' : 'Donnie', 'Salary' : '100000000'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) node4 = q.add_node(attrs4) # Test matching all nodes and then filtering with a predicate match_lst1 = q.match_node({'Label' : 'Person'}) # The predicate is salary > 2000 filtered_lst1 = pred.filter(match_lst1, 'Salary', '2000', '>') self.assertEqual(filtered_lst1, [node3, node4]) # Test matching a single node and then filtering with a predicate match_lst2 = q.match_node({'Name' : 'Alice'}) filtered_lst2 = pred.filter(match_lst2, 'Salary', '500', '=') self.assertEqual(filtered_lst2, [node1])
def __init__(self, object_list, gs): """ This class is the linker for microDB. It takes in a list of L{Command_Struct} objects that is generated by the parser, and a L{GraphStructure} object. @type object_list: List of L{Command_Struct} objects @param object_list: List of packaged commands that should be generated by the parser. @type: gs: L{GraphStructure} object @param gs: The current internal graph representation. """ self.list_objects = object_list; self.gs = gs self.query_evaluator = QueryEvaluator(gs) self.pred = Predicates(gs)
def test_match_node(self): """ Tests L{QueryEvaluator.match_node} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label': 'Person', 'Name': 'Alice'} attrs2 = {'Label': 'Person', 'Name': 'Bob'} attrs3 = {'Label': 'Person', 'Name': 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) # Test matching all node match_lst1 = q.match_node({'Label': 'Person'}) self.assertEqual(match_lst1, [node1, node2, node3]) # Test matching single node match_lst2 = q.match_node({'Name': 'Alice'}) self.assertEqual(match_lst2, [node1])
def test_add_relationship(self): """ Tests L{QueryEvaluator.add_relationship} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label': 'Person', 'Name': 'Alice'} attrs2 = {'Label': 'Person', 'Name': 'Bob'} attrs3 = {'Label': 'Person', 'Name': 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type': 'friend'} edge_attrs2 = {'rel_type': 'cousin'} # Test first edge edge1 = q.add_relationship(node1, node2, edge_attrs1) self.assertEqual(edge1, (node1[0], node2[0], edge_attrs1)) # Test second edge edge2 = q.add_relationship(node2, node3, edge_attrs2) self.assertEqual(edge2, (node2[0], node3[0], edge_attrs2))
def test_match_node_predicate(self): """ Tests applying a predicate to a simple match node query for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) pred = Predicates(gs) attrs1 = {'Label': 'Person', 'Name': 'Alice', 'Salary': '500'} attrs2 = {'Label': 'Person', 'Name': 'Bob', 'Salary': '1000'} attrs3 = {'Label': 'Person', 'Name': 'John', 'Salary': '20000'} attrs4 = {'Label': 'Person', 'Name': 'Donnie', 'Salary': '100000000'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) node4 = q.add_node(attrs4) # Test matching all nodes and then filtering with a predicate match_lst1 = q.match_node({'Label': 'Person'}) # The predicate is salary > 2000 filtered_lst1 = pred.filter(match_lst1, 'Salary', '2000', '>') self.assertEqual(filtered_lst1, [node3, node4]) # Test matching a single node and then filtering with a predicate match_lst2 = q.match_node({'Name': 'Alice'}) filtered_lst2 = pred.filter(match_lst2, 'Salary', '500', '=') self.assertEqual(filtered_lst2, [node1])
class Linker: """ A basic linker class. """ """ REL ATTR = e: a b:c ID ATTR = n: a a:b BOOL = b: a val:0/1 ID = n: a () () METHODS TO IMPLEMENT CREATE ID ATTR .. CREATEEDGE ID ATTR REL ATTR ID ATTR MATCH ID ATTR REL ATTR ID ATTR REL ATTR ID ATTR ... MODIFYNODE ID ATTR ID ATTR BOOL MODIFYEDGE REL ATTR REL ATTR BOOL DELETENODE ID ATTR DELETEEDGE REL ATTR RETURN ID ID ... HASPATH ID ATTR ID ATTR CLEAR SHORTESTPATH ID ATTR ID ATTR NEIGHBOR ID ATTR HASEDGE ID ATTR ID ATTR COMMONNEIGHBORS ID ATTR ID ATTR RESET FLUSH # EXTRA AGG [id attr (<, >, =) id attr () val ...] METHODS IMPLEMENTED CREATE ID ATTR .. CREATEEDGE ID ATTR REL ATTR ID ATTR MATCH ID ATTR REL ATTR ID ATTR REL ATTR ID ATTR ... MODIFYNODE ID ATTR ID ATTR BOOL MODIFYEDGE REL ATTR REL ATTR BOOL DELETENODE ID ATTR DELETEEDGE REL ATTR RETURN ID ID ... HASPATH ID ATTR ID ATTR CLEAR SHORTESTPATH ID ATTR ID ATTR """ def __init__(self, object_list, gs): """ This class is the linker for microDB. It takes in a list of L{Command_Struct} objects that is generated by the parser, and a L{GraphStructure} object. @type object_list: List of L{Command_Struct} objects @param object_list: List of packaged commands that should be generated by the parser. @type: gs: L{GraphStructure} object @param gs: The current internal graph representation. """ self.list_objects = object_list; self.gs = gs self.query_evaluator = QueryEvaluator(gs) self.pred = Predicates(gs) def PrintNodes(self, nodes): """ Prints a list of nodes. @type nodes: List @param nodes: Node tuples to be printed. """ if nodes == []: print bcolors.FAIL + "No matches found" + bcolors.ENDC else: print bcolors.OKGREEN + "NODE MATCHES:" + bcolors.ENDC node_num = 1 for node in nodes: print bcolors.OKBLUE + "Node " + str(node_num) + \ " = " + str(node) + bcolors.ENDC node_num += 1 def PrintNode_ids(self, node_ids): """ Prints a list of nodes. @type nodes: List @param nodes: Node tuples to be printed. """ nodes = [] for node_id in node_ids: nodes.append((node_id, self.query_evaluator.get_node_attrs(node_id))) self.PrintNodes(nodes) def PrintEdges(self, edges): """ Prints a list of edges. @type edges: List @param edges: Edge tuples to be printed. """ if edges == []: print bcolors.FAIL + "No matches found" + bcolors.ENDC else: print bcolors.OKGREEN + "EDGE MATCHES:" + bcolors.ENDC edge_num = 1 for edge in edges: edge_tup = (self.query_evaluator.get_node_attrs( edge[0]), edge[2], self.query_evaluator.get_node_attrs(edge[1])) print bcolors.OKBLUE + "Edge " + str(edge_num) + " = " + \ str(edge_tup) + bcolors.ENDC edge_num += 1 def CreateNode(self, attribute_list): """ Creates a node and sets the identifier to refer to the created node using the passed in parsed attribute list. @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ for node in attribute_list: curr_id = node[1] curr_attrs = node[2] self.gs.set_identifier(curr_id, self.query_evaluator.add_node(curr_attrs)) def CreateEdge(self, attribute_list): """ Creates an edge between the specified nodes and with the specified relationship attributes, all contained in the parsed attribute list @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ counter = 0 [nodes1_identifier, nodes1, edge_identifier, edge_attrs, nodes1_identifier, nodes2] = [0]*6 for item in attribute_list: if (counter % 3) == 0: nodes1 = self.query_evaluator.match_node(item[2]) elif (counter % 3) == 1: edge_identifier = item[1] edge_attrs = item[2] elif (counter % 3) == 2: nodes2 = self.query_evaluator.match_node(item[2]) for node1 in nodes1: for node2 in nodes2: self.query_evaluator.add_relationship(node1, node2, edge_attrs) counter += 1 def PredNodeFilters(self, nodes, keyvals): """ Checks that the specified predicate attribute is present in the attributes of all of the nodes @type nodes: List @param nodes: List of nodes @type keyvals: keyvals @param keyvals: List of attribute names to check for """ filtered_nodes = [] for node in nodes: allpreds = True for keyval in keyvals: if keyval not in node[1].keys(): allpreds = False if allpreds: filtered_nodes.append(node) return filtered_nodes def getPredAttrs (self, predicates): """ Get the list of predicate attributes from the predicates list @type predicates: List @param nodes: List of predicate parsed objects """ counter = 0 PredAttrList = [] for item in predicates: if (counter) % 2 == 0: PredAttrList.append(item[0]) counter += 1 return PredAttrList def MatchSingleItem(self, attribute_list, predicates): """ Matches a single item, either a node or a relationship, by calling the appropriate query_evaluator method. Then prints out the results of the match query @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item = attribute_list[0] curr_id = item[1] if item[0] == "n:": nodes = self.query_evaluator.match_node(item[2]) if (predicates != []): PredAttrs = self.getPredAttrs(predicates[0]) prednodes = self.PredNodeFilters(nodes, PredAttrs) filtered_nodes = self.Filter_Preds(prednodes, predicates[0]) self.gs.set_identifier(curr_id, filtered_nodes) self.PrintNodes(filtered_nodes) else: self.gs.set_identifier(curr_id, nodes) self.PrintNodes(nodes) elif item[0] == "e:": edges = self.query_evaluator.match(None, None, item[2]) self.gs.set_identifier(curr_id, edges) self.PrintEdges(edges) def Filter_Preds(self, nodeids, predicates): """ Filter nodes based on parsed predicate objects @type node_ids: List @param node_ids: Nodes to filter @type predicates: List @param pred_list: Parsed predicate objects to filter on """ if len(predicates) < 2: return self.pred.filter(nodeids, predicates[0][0], predicates[0][2], predicates[0][1]) else: lenpred = len(predicates) counter = 0 pred_list = [] bool_list = [] for item in predicates: if (counter) % 2 == 0: pred_list.append(item) elif (counter) % 2 == 1: bool_list.append(item) counter += 1 return self.getFilteredNodes(nodeids, pred_list, bool_list) def getFilteredNodes(self, nodeids, pred_list, bool_list): """ Given a list of the predicate objects and a list of boolean arguments, return the list of filtered nodes based on the predicates @type node_ids: List @param node_ids: Nodes to filter @type pred_list: List @param pred_list: Predicates to filer on @type bool_list: List @param bool_list: AND or OR strings to combine predicates """ filtered_nodes = [] for x in range(len(pred_list) - 1): if x == 0: pred0 = pred_list[x] pred1 = pred_list[x + 1] filter1 = self.pred.filter(nodeids, pred0[0], pred0[2], pred0[1]) filter2 = self.pred.filter(nodeids, pred1[0], pred1[2], pred1[1]) if bool_list[x] == 'AND': filtered_nodes = [val for val in filter1 if val in filter2] elif bool_list[x] == 'OR': for fltr in filter2: if fltr not in filter1: filter1.append(fltr) filtered_nodes = filter1 else: pred = pred_list[x + 1] fltr = self.pred.filter(filtered_nodes, pred[0], pred[2], pred[1]) if bool_list[x] == 'AND': filtered_nodes = [val for val in filtered_nodes if val in fltr] elif bool_list[x] == 'OR': filtered_nodes = list(set(filtered_nodes + fltr)) return filtered_nodes def TwoItemsFilter(self, item, preds): nodes = self.query_evaluator.match_node(item[2]) PredAttrs = self.getPredAttrs(preds) prednodes = self.PredNodeFilters(nodes, PredAttrs) filtered_nodes = self.Filter_Preds(prednodes, preds) return filtered_nodes def MatchTwoItems(self, attribute_list, predicates): """ Matches a pair of nodes and edges. @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] curr_id = item1[1] if item1[0] == "n:": filtered_nodes = None if (predicates != []): filtered_nodes = self.TwoItemsFilter(item1, predicates[0]) edges = self.query_evaluator.match_node_rel(item1[2], item2[2], filtered_nodes) self.gs.set_identifier(curr_id, edges) self.PrintEdges(edges) else: filtered_nodes = None if (predicates != []): filtered_nodes = self.TwoItemsFilter(item2, predicates[0]) edges = self.query_evaluator.match_node_rel(item2[2], item1[2], filtered_nodes) self.gs.set_identifier(curr_id, edges) self.PrintEdges(edges) def MatchThreeItems(self, attribute_list, predicates): """ Matches a node, edge, node sequence in that order @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] item3 = attribute_list[2] filtered_nodes1 = None filtered_nodes2 = None if (len(predicates) == 2): filtered_nodes1 = self.TwoItemsFilter(item1, predicates[0]) filtered_nodes2 = self.TwoItemsFilter(item3, predicates[1]) elif (len(predicates) == 1): if (item1[1] == predicates[0][0][3]): filtered_nodes1 = self.TwoItemsFilter(item1, predicates[0]) else: filtered_nodes2 = self.TwoItemsFilter(item3, predicates[0]) edges = self.query_evaluator.match_node_node_rel(item1[2], item3[2], item2[2], filtered_nodes1, filtered_nodes2) self.gs.set_identifier(item1[1], edges) self.PrintEdges(edges) def getIdList(self, attribute_list): """ Gets the list of identifiers from the attribute list @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ counter = 0 IdList = [] for item in attribute_list: if (counter % 2) == 0: IdList.append(item[1]) counter += 1 return IdList def getPredOrder(self, attribute_list, predicates): """ Calculates the order in which the predicates must be applied to the nodes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". @type predicates: List @param predicates: List of parsed predicate objects """ IdList = self.getIdList(attribute_list) predIdList = [] PredOrder = [] for pred in predicates: predIdList.append(pred[0][3]) for predId in predIdList: PredOrder.append(IdList.index(predId)) return PredOrder def MatchChain(self, attribute_list, predicates): """ Matches a chain of node, edge, node, edge, node... @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ counter = 0 node_attr_list = [] edge_attr_list = [] for item in attribute_list: if (counter) % 2 == 0: node_attr_list.append(item[2]) elif (counter) % 2 == 1: edge_attr_list.append(item[2]) counter += 1 predOrder = [] filtered_nodes = [None] * len(node_attr_list) if predicates != []: predOrder = self.getPredOrder(attribute_list, predicates) for x in predOrder: nodes1 = self.query_evaluator.match_node(node_attr_list[x]) PredAttrs1 = self.getPredAttrs(predicates[0]) prednodes1 = self.PredNodeFilters(nodes1, PredAttrs1) filtered_nodes1 = self.Filter_Preds(prednodes1, predicates[0]) filtered_nodes[x] = filtered_nodes1 predicates.pop(0) nodes = self.query_evaluator.multi_match(node_attr_list, edge_attr_list, filtered_nodes) self.gs.set_identifier(attribute_list[0][1], nodes) if nodes == None: print bcolors.FAIL + "No matches found" + bcolors.ENDC else: print bcolors.OKGREEN + "NODE MATCHES:" + bcolors.ENDC node_num = 1 for node in nodes: node_tup = (node[0], self.query_evaluator.get_node_attrs(node[0])) print bcolors.OKBLUE + "Node " + str(node_num) + \ " = " + str(node_tup) + bcolors.ENDC node_num += 1 def GeneralMatch(self, attribute_list, predicates): """ Calls the corresponding match function to match a set of ndoes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". @type predicates: List @param predicates: List of parsed predicate objects """ if (len(attribute_list) == 1): self.MatchSingleItem(attribute_list, predicates) elif(len(attribute_list) == 2): self.MatchTwoItems(attribute_list, predicates) elif(len(attribute_list) == 3): self.MatchThreeItems(attribute_list, predicates) else: self.MatchChain(attribute_list, predicates) def ModifyNode(self, attribute_list, predicates): """ Modifies the specified nodes by either adding or removing attribtues @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". @type predicates: List @param predicates: List of parsed predicate objects """ nodes_modified = attribute_list[0] attrs_changed = attribute_list[1] modify_boolean = attribute_list[2] self.query_evaluator.modify_node(nodes_modified[2], attrs_changed[2], int ((modify_boolean[2])['val'])) def ModifyEdge(self, attribute_list, predicates): """ Modifies the specified edges by either adding or removing attribtues @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". @type predicates: List @param predicates: List of parsed predicate objects """ edges_modified = attribute_list[0] attrs_changed = attribute_list[1] modify_boolean = attribute_list[2] self.query_evaluator.modify_rel(edges_modified[2], attrs_changed[2], int ((modify_boolean[2])['val'])) def ReturnIdent(self, attribute_list): """ Returns the specified identifier @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ for item in attribute_list: print bcolors.OKBLUE + str(item[1]) + " = " \ + str(self.gs.get_identifier(item[1])) + bcolors.ENDC def HasPath(self, attribute_list): """ Checks if a path exists between two ndoes. @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] nodes1 = self.query_evaluator.match(item1[2], None, None) nodes2 = self.query_evaluator.match(item2[2], None, None) for node1 in nodes1: for node2 in nodes2: if (self.query_evaluator.check_path(node1[0], node2[0])): print bcolors.OKBLUE + "A path exists between " \ + str(node1) + " and " + str(node2) + bcolors.ENDC else: print bcolors.FAIL + "No path exists between " \ + str(node1) + " and " + str(node2) + bcolors.ENDC def ShortestPath(self, attribute_list): """ Returns the shortest path between two nodes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] nodes1 = self.query_evaluator.match(item1[2], None, None) nodes2 = self.query_evaluator.match(item2[2], None, None) for node1 in nodes1: for node2 in nodes2: if (self.query_evaluator.check_path(node1[0], node2[0])): path_list = self.query_evaluator.get_shortest_path\ (node1[0], node2[0]) print bcolors.OKGREEN \ + "The nodes in the path between " + str(node1) \ + " and " + str(node2) + " are: " + bcolors.ENDC for node_id in path_list: print bcolors.OKBLUE \ + str((node_id, self.query_evaluator.get_node_attrs\ (node_id))) + bcolors.ENDC else: print bcolors.FAIL + "No path exists between " + \ str(node1)+ " and " + str(node2) + bcolors.ENDC def getNeighbors(self, attribute_list): """ Get the neighbors of the specified nodes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] nodes = self.query_evaluator.match(item1[2], None, None) if nodes == None: print bcolors.FAIL + "No Node matches found" + bcolors.ENDC else: print bcolors.OKGREEN + "NODE Neighbors:" + bcolors.ENDC node_num = 1 for node1 in nodes: neighbor_ids = self.query_evaluator.get_neighbors(node1[0]) if (neighbor_ids == []): print bcolors.FAIL + "Neighbors for Node " + \ str(node_num) + " = " + "No neighbors for Node(s)" + \ bcolors.ENDC else: neighbors = [] for neighbor_id in neighbor_ids: neighbors.append((neighbor_id, self.query_evaluator.get_node_attrs(neighbor_id))) print bcolors.OKBLUE + "Neighbors for Node " + \ str(node_num) + " = " + str(neighbors) + bcolors.ENDC node_num += 1 def HasEdge(self, attribute_list): """ Checks if a direct edge exists between two nodes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] nodes1 = self.query_evaluator.match(item1[2], None, None) nodes2 = self.query_evaluator.match(item2[2], None, None) for node1 in nodes1: for node2 in nodes2: if (self.query_evaluator.check_path(node1[0], node2[0])): print bcolors.OKBLUE + \ "A direct edge exists between " + str(node1) + \ " and " + str(node2) + bcolors.ENDC else: print bcolors.FAIL + "No direct edge exists between " + \ str(node1) + " and " + str(node2) + bcolors.ENDC def execute(self): """ Executes commands that were extracted by the parser. """ # iterate through objects returned by parser to execute queries for obj in self.list_objects: command_name = obj.get_command() attribute_list = obj.get_attr_list() predicates = obj.get_names() if command_name == "CREATE": self.CreateNode(attribute_list) elif command_name == "CREATEEDGE": self.CreateEdge(attribute_list) elif command_name == "MATCH": self.GeneralMatch(attribute_list, predicates) elif command_name == "MODIFYNODE": self.ModifyNode(attribute_list, predicates) elif command_name == "MODIFYEDGE": self.ModifyEdge(attribute_list, predicates) elif command_name == "DELETENODE": node_deleted = attribute_list[0] self.query_evaluator.delete_node(node_deleted[2]) elif command_name == "DELETEEDGE": edge_deleted = attribute_list[0] self.query_evaluator.delete_rel(edge_deleted[2]) elif command_name == "RETURN": self.ReturnIdent(attribute_list) elif command_name == "HASPATH": self.HasPath(attribute_list) elif command_name == "CLEAR": self.query_evaluator.clear() elif command_name == "SHORTESTPATH": self.ShortestPath(attribute_list) elif command_name == "SHOW": self.gs.display() elif command_name == "VISUALIZE": self.query_evaluator.create_visual() elif command_name == "NEIGHBOR": self.getNeighbors(attribute_list) elif command_name == "HASEDGE": self.HasEdge(attribute_list)
def test_multi_match(self): """ Test L{QueryEvaluator.multi_match} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label': 'Person', 'Name': 'Alice'} attrs2 = {'Label': 'Person', 'Name': 'Bob'} attrs3 = {'Label': 'Person', 'Name': 'John'} attrs4 = {'Label': 'Person', 'Name': 'Rick'} attrs5 = {'Label': 'Person', 'Name': 'Cat'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) node4 = q.add_node(attrs4) node5 = q.add_node(attrs5) edge_attrs1 = {'rel_type': 'friend'} edge_attrs2 = {'rel_type': 'friend', 'fam': 'cousin'} edge_attrs3 = {'rel_type': 'dad'} edge_attrs4 = {'rel_type': 'mom'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) edge3 = q.add_relationship(node3, node4, edge_attrs3) edge4 = q.add_relationship(node4, node5, edge_attrs4) # Test no match for multiple length query result1 = q.multi_match([attrs1, attrs2, attrs3], [edge_attrs3, edge_attrs1]) self.assertEqual(result1, None) # Test single match for multiple length query result2 = q.multi_match([attrs1, attrs2, attrs3], [edge_attrs1, edge_attrs2]) self.assertEqual(result2, [(1, 3)]) # Tests many matches for multiple length query result3 = q.multi_match([{ 'Label': 'Person' }, { 'Label': 'Person' }], [edge_attrs1]) self.assertEqual(result3, [edge1, edge2]) # Test all matches for multiple length query result4 = q.multi_match([{}, {}], [{}]) self.assertEqual(result4, [edge1, edge2, edge3, edge4])
def test_modify_rel(self): """ Test L{QueryEvaluator.modify_rel} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label': 'Person', 'Name': 'Alice'} attrs2 = {'Label': 'Person', 'Name': 'Bob'} attrs3 = {'Label': 'Person', 'Name': 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type': 'friend'} edge_attrs2 = {'rel_type': 'friend', 'fam': 'cousin'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) # Tests adding attributes to relationship q.modify_rel(edge_attrs2, {'like': 'no'}, True) match_lst1 = q.match_rel(edge_attrs2) result1 = [(node2[0], node3[0], { 'rel_type': 'friend', 'fam': 'cousin', 'like': 'no' })] self.assertEqual(sorted(match_lst1), sorted(result1)) # Tests deleting attributes to relationship q.modify_rel(edge_attrs2, {'like': 'no'}, False) match_lst2 = q.match_rel(edge_attrs2) result2 = [(node2[0], node3[0], edge_attrs2)] self.assertEqual(sorted(match_lst2), sorted(result2))
def test_modify_node(self): """ Tests L{QueryEvaluator.modify_node} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label': 'Person', 'Name': 'Alice'} attrs2 = {'Label': 'Person', 'Name': 'Bob'} attrs3 = {'Label': 'Person', 'Name': 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type': 'friend'} edge_attrs2 = {'rel_type': 'friend', 'fam': 'cousin'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) # Tests adding attributes to node q.modify_node(attrs1, {'Age': '10'}, True) match_lst1 = q.match_node(attrs1) result1 = [(node1[0], { 'Label': 'Person', 'Name': 'Alice', 'Age': '10' })] self.assertEqual(match_lst1, result1) # Tests removing attributes to node q.modify_node(attrs1, {'Age': '10'}, False) match_lst2 = q.match_node(attrs1) result2 = [(node1[0], attrs1)] self.assertEqual(match_lst2, result2)
def test_delete_rel(self): """ Tests L{QueryEvaluator.delete_rel} method for L{QueryEvaluator}. """ gs = GraphStructure() q = QueryEvaluator(gs) attrs1 = {'Label': 'Person', 'Name': 'Alice'} attrs2 = {'Label': 'Person', 'Name': 'Bob'} attrs3 = {'Label': 'Person', 'Name': 'John'} node1 = q.add_node(attrs1) node2 = q.add_node(attrs2) node3 = q.add_node(attrs3) edge_attrs1 = {'rel_type': 'friend'} edge_attrs2 = {'rel_type': 'friend', 'fam': 'cousin'} edge1 = q.add_relationship(node1, node2, edge_attrs1) edge2 = q.add_relationship(node2, node3, edge_attrs2) # Tests deleting no relationship q.delete_rel({'rel_type': 'friend', 'fam': 'dad'}) match_lst1 = q.match({}, {}, {}) result1 = [(node1[0], node2[0], edge_attrs1), (node2[0], node3[0], edge_attrs2)] self.assertEqual(match_lst1, result1) # Tests deleting relationship q.delete_rel(edge_attrs1) match_lst2 = q.match({}, {}, {}) result2 = [] self.assertEqual(match_lst2, result2)
class LoadData: """ Class is responsible for taking a text file in a certain format and loading add the nodes and edges into the in memory Graph Database. """ def __init__(self, gs): """ Takes a L{GraphStructure} object to load the data into. @type gs: L{GraphStructure} object @param gs: L{GraphStructure} object that is used to store nodes and edges in. """ self.gs = gs self.gstorage = GraphStorage(self.gs) # Loads data on disk self.graph_file = 'graph_file' self.id_file = 'id_file' self.load_data() # Sets up a QueryEvaluator object to perform the loading operations self.q_eval = QueryEvaluator(gs) def load_data(self): """ Loads persisted data on disk, if it exists, into our L{GraphStructure} object. """ if Utilities.files_exist(self.graph_file, self.id_file): self.gstorage.load_graph(self.graph_file, self.id_file) def load_text_file(self, text_file): """ Loads the data from the text file into the in memory graph structure stored in the L{QueryEvaluator} object and saves the data onto disk. """ # Stores a set of nodes and edges node = set() edge = set() f = open(text_file, 'r') for line in f: # Skips commented lines in text file if line[0] == '#': continue # Stores nodes and edges in our set data structure line = line.strip().split('\t') node1, node2 = line[0], line[1] node.add(node1) node.add(node2) edge.add((node1, node2)) f.close() # Stores return value when a node is added node_dict = {} # Adds node and edges between the nodes in our graph database for n in node: n1 = self.q_eval.add_node({'id' : n}) node_dict[n] = n1 for node1,node2 in edge: self.q_eval.add_relationship(node_dict[node1], node_dict[node2], {}) # Saves the file to disk self.gstorage.write_graph(self.graph_file, self.id_file)
class Linker: """ A basic linker class. """ """ REL ATTR = e: a b:c ID ATTR = n: a a:b BOOL = b: a val:0/1 ID = n: a () () METHODS TO IMPLEMENT CREATE ID ATTR .. CREATEEDGE ID ATTR REL ATTR ID ATTR MATCH ID ATTR REL ATTR ID ATTR REL ATTR ID ATTR ... MODIFYNODE ID ATTR ID ATTR BOOL MODIFYEDGE REL ATTR REL ATTR BOOL DELETENODE ID ATTR DELETEEDGE REL ATTR RETURN ID ID ... HASPATH ID ATTR ID ATTR CLEAR SHORTESTPATH ID ATTR ID ATTR NEIGHBOR ID ATTR HASEDGE ID ATTR ID ATTR COMMONNEIGHBORS ID ATTR ID ATTR RESET FLUSH # EXTRA AGG [id attr (<, >, =) id attr () val ...] METHODS IMPLEMENTED CREATE ID ATTR .. CREATEEDGE ID ATTR REL ATTR ID ATTR MATCH ID ATTR REL ATTR ID ATTR REL ATTR ID ATTR ... MODIFYNODE ID ATTR ID ATTR BOOL MODIFYEDGE REL ATTR REL ATTR BOOL DELETENODE ID ATTR DELETEEDGE REL ATTR RETURN ID ID ... HASPATH ID ATTR ID ATTR CLEAR SHORTESTPATH ID ATTR ID ATTR """ def __init__(self, object_list, gs): """ This class is the linker for microDB. It takes in a list of L{Command_Struct} objects that is generated by the parser, and a L{GraphStructure} object. @type object_list: List of L{Command_Struct} objects @param object_list: List of packaged commands that should be generated by the parser. @type: gs: L{GraphStructure} object @param gs: The current internal graph representation. """ self.list_objects = object_list self.gs = gs self.query_evaluator = QueryEvaluator(gs) self.pred = Predicates(gs) def PrintNodes(self, nodes): """ Prints a list of nodes. @type nodes: List @param nodes: Node tuples to be printed. """ if nodes == []: print bcolors.FAIL + "No matches found" + bcolors.ENDC else: print bcolors.OKGREEN + "NODE MATCHES:" + bcolors.ENDC node_num = 1 for node in nodes: print bcolors.OKBLUE + "Node " + str(node_num) + \ " = " + str(node) + bcolors.ENDC node_num += 1 def PrintNode_ids(self, node_ids): """ Prints a list of nodes. @type nodes: List @param nodes: Node tuples to be printed. """ nodes = [] for node_id in node_ids: nodes.append( (node_id, self.query_evaluator.get_node_attrs(node_id))) self.PrintNodes(nodes) def PrintEdges(self, edges): """ Prints a list of edges. @type edges: List @param edges: Edge tuples to be printed. """ if edges == []: print bcolors.FAIL + "No matches found" + bcolors.ENDC else: print bcolors.OKGREEN + "EDGE MATCHES:" + bcolors.ENDC edge_num = 1 for edge in edges: edge_tup = (self.query_evaluator.get_node_attrs(edge[0]), edge[2], self.query_evaluator.get_node_attrs(edge[1])) print bcolors.OKBLUE + "Edge " + str(edge_num) + " = " + \ str(edge_tup) + bcolors.ENDC edge_num += 1 def CreateNode(self, attribute_list): """ Creates a node and sets the identifier to refer to the created node using the passed in parsed attribute list. @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ for node in attribute_list: curr_id = node[1] curr_attrs = node[2] self.gs.set_identifier(curr_id, self.query_evaluator.add_node(curr_attrs)) def CreateEdge(self, attribute_list): """ Creates an edge between the specified nodes and with the specified relationship attributes, all contained in the parsed attribute list @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ counter = 0 [ nodes1_identifier, nodes1, edge_identifier, edge_attrs, nodes1_identifier, nodes2 ] = [0] * 6 for item in attribute_list: if (counter % 3) == 0: nodes1 = self.query_evaluator.match_node(item[2]) elif (counter % 3) == 1: edge_identifier = item[1] edge_attrs = item[2] elif (counter % 3) == 2: nodes2 = self.query_evaluator.match_node(item[2]) for node1 in nodes1: for node2 in nodes2: self.query_evaluator.add_relationship( node1, node2, edge_attrs) counter += 1 def PredNodeFilters(self, nodes, keyvals): """ Checks that the specified predicate attribute is present in the attributes of all of the nodes @type nodes: List @param nodes: List of nodes @type keyvals: keyvals @param keyvals: List of attribute names to check for """ filtered_nodes = [] for node in nodes: allpreds = True for keyval in keyvals: if keyval not in node[1].keys(): allpreds = False if allpreds: filtered_nodes.append(node) return filtered_nodes def getPredAttrs(self, predicates): """ Get the list of predicate attributes from the predicates list @type predicates: List @param nodes: List of predicate parsed objects """ counter = 0 PredAttrList = [] for item in predicates: if (counter) % 2 == 0: PredAttrList.append(item[0]) counter += 1 return PredAttrList def MatchSingleItem(self, attribute_list, predicates): """ Matches a single item, either a node or a relationship, by calling the appropriate query_evaluator method. Then prints out the results of the match query @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item = attribute_list[0] curr_id = item[1] if item[0] == "n:": nodes = self.query_evaluator.match_node(item[2]) if (predicates != []): PredAttrs = self.getPredAttrs(predicates[0]) prednodes = self.PredNodeFilters(nodes, PredAttrs) filtered_nodes = self.Filter_Preds(prednodes, predicates[0]) self.gs.set_identifier(curr_id, filtered_nodes) self.PrintNodes(filtered_nodes) else: self.gs.set_identifier(curr_id, nodes) self.PrintNodes(nodes) elif item[0] == "e:": edges = self.query_evaluator.match(None, None, item[2]) self.gs.set_identifier(curr_id, edges) self.PrintEdges(edges) def Filter_Preds(self, nodeids, predicates): """ Filter nodes based on parsed predicate objects @type node_ids: List @param node_ids: Nodes to filter @type predicates: List @param pred_list: Parsed predicate objects to filter on """ if len(predicates) < 2: return self.pred.filter(nodeids, predicates[0][0], predicates[0][2], predicates[0][1]) else: lenpred = len(predicates) counter = 0 pred_list = [] bool_list = [] for item in predicates: if (counter) % 2 == 0: pred_list.append(item) elif (counter) % 2 == 1: bool_list.append(item) counter += 1 return self.getFilteredNodes(nodeids, pred_list, bool_list) def getFilteredNodes(self, nodeids, pred_list, bool_list): """ Given a list of the predicate objects and a list of boolean arguments, return the list of filtered nodes based on the predicates @type node_ids: List @param node_ids: Nodes to filter @type pred_list: List @param pred_list: Predicates to filer on @type bool_list: List @param bool_list: AND or OR strings to combine predicates """ filtered_nodes = [] for x in range(len(pred_list) - 1): if x == 0: pred0 = pred_list[x] pred1 = pred_list[x + 1] filter1 = self.pred.filter(nodeids, pred0[0], pred0[2], pred0[1]) filter2 = self.pred.filter(nodeids, pred1[0], pred1[2], pred1[1]) if bool_list[x] == 'AND': filtered_nodes = [val for val in filter1 if val in filter2] elif bool_list[x] == 'OR': for fltr in filter2: if fltr not in filter1: filter1.append(fltr) filtered_nodes = filter1 else: pred = pred_list[x + 1] fltr = self.pred.filter(filtered_nodes, pred[0], pred[2], pred[1]) if bool_list[x] == 'AND': filtered_nodes = [ val for val in filtered_nodes if val in fltr ] elif bool_list[x] == 'OR': filtered_nodes = list(set(filtered_nodes + fltr)) return filtered_nodes def TwoItemsFilter(self, item, preds): nodes = self.query_evaluator.match_node(item[2]) PredAttrs = self.getPredAttrs(preds) prednodes = self.PredNodeFilters(nodes, PredAttrs) filtered_nodes = self.Filter_Preds(prednodes, preds) return filtered_nodes def MatchTwoItems(self, attribute_list, predicates): """ Matches a pair of nodes and edges. @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] curr_id = item1[1] if item1[0] == "n:": filtered_nodes = None if (predicates != []): filtered_nodes = self.TwoItemsFilter(item1, predicates[0]) edges = self.query_evaluator.match_node_rel( item1[2], item2[2], filtered_nodes) self.gs.set_identifier(curr_id, edges) self.PrintEdges(edges) else: filtered_nodes = None if (predicates != []): filtered_nodes = self.TwoItemsFilter(item2, predicates[0]) edges = self.query_evaluator.match_node_rel( item2[2], item1[2], filtered_nodes) self.gs.set_identifier(curr_id, edges) self.PrintEdges(edges) def MatchThreeItems(self, attribute_list, predicates): """ Matches a node, edge, node sequence in that order @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] item3 = attribute_list[2] filtered_nodes1 = None filtered_nodes2 = None if (len(predicates) == 2): filtered_nodes1 = self.TwoItemsFilter(item1, predicates[0]) filtered_nodes2 = self.TwoItemsFilter(item3, predicates[1]) elif (len(predicates) == 1): if (item1[1] == predicates[0][0][3]): filtered_nodes1 = self.TwoItemsFilter(item1, predicates[0]) else: filtered_nodes2 = self.TwoItemsFilter(item3, predicates[0]) edges = self.query_evaluator.match_node_node_rel( item1[2], item3[2], item2[2], filtered_nodes1, filtered_nodes2) self.gs.set_identifier(item1[1], edges) self.PrintEdges(edges) def getIdList(self, attribute_list): """ Gets the list of identifiers from the attribute list @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ counter = 0 IdList = [] for item in attribute_list: if (counter % 2) == 0: IdList.append(item[1]) counter += 1 return IdList def getPredOrder(self, attribute_list, predicates): """ Calculates the order in which the predicates must be applied to the nodes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". @type predicates: List @param predicates: List of parsed predicate objects """ IdList = self.getIdList(attribute_list) predIdList = [] PredOrder = [] for pred in predicates: predIdList.append(pred[0][3]) for predId in predIdList: PredOrder.append(IdList.index(predId)) return PredOrder def MatchChain(self, attribute_list, predicates): """ Matches a chain of node, edge, node, edge, node... @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ counter = 0 node_attr_list = [] edge_attr_list = [] for item in attribute_list: if (counter) % 2 == 0: node_attr_list.append(item[2]) elif (counter) % 2 == 1: edge_attr_list.append(item[2]) counter += 1 predOrder = [] filtered_nodes = [None] * len(node_attr_list) if predicates != []: predOrder = self.getPredOrder(attribute_list, predicates) for x in predOrder: nodes1 = self.query_evaluator.match_node(node_attr_list[x]) PredAttrs1 = self.getPredAttrs(predicates[0]) prednodes1 = self.PredNodeFilters(nodes1, PredAttrs1) filtered_nodes1 = self.Filter_Preds(prednodes1, predicates[0]) filtered_nodes[x] = filtered_nodes1 predicates.pop(0) nodes = self.query_evaluator.multi_match(node_attr_list, edge_attr_list, filtered_nodes) self.gs.set_identifier(attribute_list[0][1], nodes) if nodes == None: print bcolors.FAIL + "No matches found" + bcolors.ENDC else: print bcolors.OKGREEN + "NODE MATCHES:" + bcolors.ENDC node_num = 1 for node in nodes: node_tup = (node[0], self.query_evaluator.get_node_attrs(node[0])) print bcolors.OKBLUE + "Node " + str(node_num) + \ " = " + str(node_tup) + bcolors.ENDC node_num += 1 def GeneralMatch(self, attribute_list, predicates): """ Calls the corresponding match function to match a set of ndoes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". @type predicates: List @param predicates: List of parsed predicate objects """ if (len(attribute_list) == 1): self.MatchSingleItem(attribute_list, predicates) elif (len(attribute_list) == 2): self.MatchTwoItems(attribute_list, predicates) elif (len(attribute_list) == 3): self.MatchThreeItems(attribute_list, predicates) else: self.MatchChain(attribute_list, predicates) def ModifyNode(self, attribute_list, predicates): """ Modifies the specified nodes by either adding or removing attribtues @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". @type predicates: List @param predicates: List of parsed predicate objects """ nodes_modified = attribute_list[0] attrs_changed = attribute_list[1] modify_boolean = attribute_list[2] self.query_evaluator.modify_node(nodes_modified[2], attrs_changed[2], int((modify_boolean[2])['val'])) def ModifyEdge(self, attribute_list, predicates): """ Modifies the specified edges by either adding or removing attribtues @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". @type predicates: List @param predicates: List of parsed predicate objects """ edges_modified = attribute_list[0] attrs_changed = attribute_list[1] modify_boolean = attribute_list[2] self.query_evaluator.modify_rel(edges_modified[2], attrs_changed[2], int((modify_boolean[2])['val'])) def ReturnIdent(self, attribute_list): """ Returns the specified identifier @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ for item in attribute_list: print bcolors.OKBLUE + str(item[1]) + " = " \ + str(self.gs.get_identifier(item[1])) + bcolors.ENDC def HasPath(self, attribute_list): """ Checks if a path exists between two ndoes. @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] nodes1 = self.query_evaluator.match(item1[2], None, None) nodes2 = self.query_evaluator.match(item2[2], None, None) for node1 in nodes1: for node2 in nodes2: if (self.query_evaluator.check_path(node1[0], node2[0])): print bcolors.OKBLUE + "A path exists between " \ + str(node1) + " and " + str(node2) + bcolors.ENDC else: print bcolors.FAIL + "No path exists between " \ + str(node1) + " and " + str(node2) + bcolors.ENDC def ShortestPath(self, attribute_list): """ Returns the shortest path between two nodes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] nodes1 = self.query_evaluator.match(item1[2], None, None) nodes2 = self.query_evaluator.match(item2[2], None, None) for node1 in nodes1: for node2 in nodes2: if (self.query_evaluator.check_path(node1[0], node2[0])): path_list = self.query_evaluator.get_shortest_path\ (node1[0], node2[0]) print bcolors.OKGREEN \ + "The nodes in the path between " + str(node1) \ + " and " + str(node2) + " are: " + bcolors.ENDC for node_id in path_list: print bcolors.OKBLUE \ + str((node_id, self.query_evaluator.get_node_attrs\ (node_id))) + bcolors.ENDC else: print bcolors.FAIL + "No path exists between " + \ str(node1)+ " and " + str(node2) + bcolors.ENDC def getNeighbors(self, attribute_list): """ Get the neighbors of the specified nodes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] nodes = self.query_evaluator.match(item1[2], None, None) if nodes == None: print bcolors.FAIL + "No Node matches found" + bcolors.ENDC else: print bcolors.OKGREEN + "NODE Neighbors:" + bcolors.ENDC node_num = 1 for node1 in nodes: neighbor_ids = self.query_evaluator.get_neighbors(node1[0]) if (neighbor_ids == []): print bcolors.FAIL + "Neighbors for Node " + \ str(node_num) + " = " + "No neighbors for Node(s)" + \ bcolors.ENDC else: neighbors = [] for neighbor_id in neighbor_ids: neighbors.append( (neighbor_id, self.query_evaluator.get_node_attrs(neighbor_id))) print bcolors.OKBLUE + "Neighbors for Node " + \ str(node_num) + " = " + str(neighbors) + bcolors.ENDC node_num += 1 def HasEdge(self, attribute_list): """ Checks if a direct edge exists between two nodes @type attribute_list: List @param attribute_list: List of parsed objects, where each element is of the form "Type: Identifier dictionary_attributes". """ item1 = attribute_list[0] item2 = attribute_list[1] nodes1 = self.query_evaluator.match(item1[2], None, None) nodes2 = self.query_evaluator.match(item2[2], None, None) for node1 in nodes1: for node2 in nodes2: if (self.query_evaluator.check_path(node1[0], node2[0])): print bcolors.OKBLUE + \ "A direct edge exists between " + str(node1) + \ " and " + str(node2) + bcolors.ENDC else: print bcolors.FAIL + "No direct edge exists between " + \ str(node1) + " and " + str(node2) + bcolors.ENDC def execute(self): """ Executes commands that were extracted by the parser. """ # iterate through objects returned by parser to execute queries for obj in self.list_objects: command_name = obj.get_command() attribute_list = obj.get_attr_list() predicates = obj.get_names() if command_name == "CREATE": self.CreateNode(attribute_list) elif command_name == "CREATEEDGE": self.CreateEdge(attribute_list) elif command_name == "MATCH": self.GeneralMatch(attribute_list, predicates) elif command_name == "MODIFYNODE": self.ModifyNode(attribute_list, predicates) elif command_name == "MODIFYEDGE": self.ModifyEdge(attribute_list, predicates) elif command_name == "DELETENODE": node_deleted = attribute_list[0] self.query_evaluator.delete_node(node_deleted[2]) elif command_name == "DELETEEDGE": edge_deleted = attribute_list[0] self.query_evaluator.delete_rel(edge_deleted[2]) elif command_name == "RETURN": self.ReturnIdent(attribute_list) elif command_name == "HASPATH": self.HasPath(attribute_list) elif command_name == "CLEAR": self.query_evaluator.clear() elif command_name == "SHORTESTPATH": self.ShortestPath(attribute_list) elif command_name == "SHOW": self.gs.display() elif command_name == "VISUALIZE": self.query_evaluator.create_visual() elif command_name == "NEIGHBOR": self.getNeighbors(attribute_list) elif command_name == "HASEDGE": self.HasEdge(attribute_list)