def get_triple(cls, id_): """ 返回三元组节点 :rtype: list[Node] :param id_: 节点uuid :return: s节点, p节点, o节点 """ node = NodeMatcher(graph_).match(cls.__name__, id=id_).first() r_matcher = RelationshipMatcher(graph_) r = r_matcher.match((node, None), "HAS_SUBJECT").first() # r.__repr__() print(r) subject_node = r.end_node r_matcher = RelationshipMatcher(graph_) r = r_matcher.match((node, None), "HAS_PREDICATE").first() print(r) predictate_node = r.end_node r_matcher = RelationshipMatcher(graph_) r = r_matcher.match((node, None), "HAS_OBJECT").first() print(r) object_node = r.end_node return subject_node, predictate_node, object_node
def rate_post(post_id, relation, username): # get current time for time of rating time = get_time() try: # get user node matcher = NodeMatcher(GRAPH) user_node = matcher.match("User", username=username).first() # get post node post_node = matcher.match("Post", post_id=post_id).first() if user_node is not None and post_node is not None: # get relationship matcher rel_matcher = RelationshipMatcher(GRAPH) # check if the user has already liked/disliked the post already_liked = rel_matcher.match([user_node, post_node], 'LIKED').first() already_disliked = rel_matcher.match([user_node, post_node], 'DISLIKED').first() # if the user is trying to rate a post the same way twice, their rating is removed if already_liked is not None and relation == "LIKED": GRAPH.separate(already_liked) return str(True) elif already_disliked is not None and relation == "DISLIKED": GRAPH.separate(already_disliked) return str(True) # if the user is switching their rating, we delete to old one, and create a new one elif already_liked is not None and relation == "DISLIKED": GRAPH.separate(already_liked) elif already_disliked is not None and relation == "LIKED": GRAPH.separate(already_disliked) # create relationship between user and post GRAPH.merge( Relationship(user_node, relation, post_node, rate_time=time), relation) return str(True) else: print("Either the user or the post couldn't be found") return str(False) except Exception as e: print(e) return str(False)
def main(): MDG = Graph() tx = MDG.begin() node_matcher = NodeMatcher(MDG) rel_matcher = RelationshipMatcher(MDG) all_nodes = node_matcher.match("Artifact") for node in all_nodes: nexts = rel_matcher.match(nodes=(node, None), r_type="NEXT") if len(nexts) <= 1: continue if len(nexts) > 2: exceptions.write(node[coordinates] + ": node has 3 or more NEXT!\n") continue seq_next = [] seq_rel = [] for r in nexts: seq_rel.append(r) i = 0 for n in walk(r): if i == 1: seq_next.append(n) r1, r2 = seq_rel[0], seq_rel[1] n1, n2 = seq_next[0], seq_next[1] if n1["version"] < n2["version"]: tx.separate(r2) else: tx.separate(r1) tx.commit()
def create_relationship(graph, rel_tuple): """ create the new rel in the graph if the rel doesn't exist, create new nodes if necessary :param graph: :param rel_tuple: :return: """ label_1 = str(rel_tuple[0][0]) name_1 = str(rel_tuple[0][1]) label_2 = str(rel_tuple[2][0]) name_2 = str(rel_tuple[2][1]) rel_type = str(rel_tuple[1][0]) rel_name = str(rel_tuple[1][1]) # check dup matcher = NodeMatcher(graph) node_1 = matcher.match(label_1, name=name_1).first() node_2 = matcher.match(label_2, name=name_2).first() if node_1 and node_2: r_matcher = RelationshipMatcher(graph) first_rel = r_matcher.match([node_1, node_2], rel_type, name=rel_name).first() if first_rel: return elif node_1 and not node_2: node_2 = Node(label_2, name=name_2) elif node_2 and not node_1: node_1 = Node(label_1, name=name_1) else: node_1 = Node(label_1, name=name_1) node_2 = Node(label_2, name=name_2) # create rel rel = Relationship(node_1, rel_type, node_2, name=rel_name) graph.create(rel)
def get_rels_from_db(graph): graph = connect_graph() matcher = RelationshipMatcher(graph) relationships = list(matcher.match()) rel_data = [] for rel in relationships: rel_json = { 'direction': rel['direction'], 'length': rel['length'], 'is_tram': rel['is_tram'], 'is_bus': rel['is_bus'], 'is_trolleybus': rel['is_trolleybus'], 'is_connector': rel['is_connector'], 'link_type_id': rel['link_type_id'], 'pedestrian_mode_id': rel['pedestrian_mode_id'], 'move_time': rel['move_time'], 'walking_time': rel['walking_time'], 'null_time': rel['null_time'], 'time_bus': rel['time_bus'], 'time_tram': rel['time_tram'], 'speed': rel['speed'], 'node_id_from': rel.start_node.identity, 'node_id_to': rel.end_node.identity } rel_data.append(rel_json) return rel_data
def getRelations(): start_type = request.args['start_type'] start_node = request.args['start_node'] end_node = request.args['end_node'] end_type = request.args['end_type'] rel_type = request.args['rel_type'] results = [] r_matcher = RelationshipMatcher(DB) # 条件0: 没有给出任何信息 if not rel_type and not start_type and not start_node and not end_node and not end_type: return jsonify({'code': '1001', 'msg': 'no messages'}) # 条件1:没给出开始节点和结束节点的任何信息,但给出关系类型 elif rel_type and not start_type and not start_node and not end_node and not end_type: for re in r_matcher.match(r_type=rel_type): results.append({ 'start_node': re.start_node['name'], 'end_node': re.end_node['name'], 'attr': dict(re) }) return jsonify(results) # 条件2:给出了开始节点或者结束节点 elif start_node or end_node: results = [] # 条件2.1: 并且给出关系类型 if rel_type: matcher = RelationshipMatch(DB, r_type=rel_type) # 条件2.2:没有给出关系类型 else: matcher = RelationshipMatch(DB) # 条件2.3:同时给出了开始节点和结束节点 if start_node and end_node: for re in matcher.where('a.name="%s" AND b.name= "%s"' % (start_node, end_node)): results.append({ 'start_node': re.start_node['name'], 'end_node': re.end_node['name'], 'attr': dict(re) }) # 条件2.4:只存在开始节点,没有结束节点 elif start_node and not end_node: for re in matcher.where('a.name="%s"' % start_node): results.append({ 'start_node': re.start_node['name'], 'end_node': re.end_node['name'], 'attr': dict(re) }) # 条件2.5:只存在结束节点不存在开始节点 elif end_node and not start_node: for re in matcher.where('b.name= "%s"' % end_node): results.append({ 'start_node': re.start_node['name'], 'end_node': re.end_node['name'], 'attr': dict(re) }) return jsonify(results) else: return jsonify({'code': '1002', 'msg': 'error messages'})
def processItem(item): neo4jGraph = item node_labels = neo4jGraph.schema.node_labels relationship_types = neo4jGraph.schema.relationship_types node_matcher = NodeMatcher(neo4jGraph) relationship_matcher = RelationshipMatcher(neo4jGraph) vertices = [] edges = [] nodes = [] for node_label in node_labels: nodes = nodes + (list(node_matcher.match(node_label))) print(nodes) for node in nodes: #Check if they have X, Y, Z coordinates if ('x' in node.keys()) and ('y' in node.keys()) and ( 'z' in node.keys()) or ('X' in node.keys()) and ( 'Y' in node.keys()) and ('Z' in node.keys()): x = node['x'] y = node['y'] z = node['z'] vertex = topologic.Vertex.ByCoordinates(x, y, z) else: vertex = randomVertex(vertices, 1) keys = list(node.keys()) values = [] for key in keys: values.append(node[key]) d = processKeysValues(keys, values) _ = vertex.SetDictionary(d) vertices.append(vertex) for node in nodes: for relationship_type in relationship_types: relationships = list( relationship_matcher.match([node], r_type=relationship_type)) for relationship in relationships: print(" ", relationship.start_node['name'], relationship_type, relationship.end_node['name']) print("Nodes Index:", nodes.index(relationship.start_node)) sv = vertices[nodes.index(relationship.start_node)] ev = vertices[nodes.index(relationship.end_node)] edge = topologic.Edge.ByStartVertexEndVertex(sv, ev) if relationship.start_node['name']: sv_name = relationship.start_node['name'] else: sv_name = 'None' if relationship.end_node['name']: ev_name = relationship.end_node['name'] else: ev_name = 'None' d = processKeysValues(["relationship_type", "from", "to"], [relationship_type, sv_name, ev_name]) if d: _ = edge.SetDictionary(d) edges.append(edge) return topologic.Graph.ByVerticesEdges(vertices, edges)
def returnPodcasts(): # Connect to database graph = Graph("http://*****:*****@localhost:7474") nodematcher = NodeMatcher(graph) relamatcher = RelationshipMatcher(graph) # Find the nodes for the cast members and the podcast. castNodes = nodematcher.match("CAST") podcastNodes = nodematcher.match("PODCAST") nodes = [] # Convert the nodes to GraphJSON format for Alchemy.js for node in castNodes: nodes.append({ "id": node.identity, "name": node["name"], "rta": node["rta"], "tp": node["tp"], "ao": node["ao"] }) for node in podcastNodes: nodes.append({ "id": node.identity, "name": node["name"], "rta": node["rta"], "tp": node["tp"], "ao": node["ao"] }) jsonNodes = dumps(nodes) # Find the Relationships within the database relationships = relamatcher.match(None, "APPEARED_ON") edges = [] # Convert the relationships to GraphJSON for rel in relationships: edges.append({ "source": rel.start_node.identity, "target": rel.end_node.identity, "role": "appeared_on" }) jsonEdges = dumps(edges) # Create a json string with all GraphJSON finalJson = '{"nodes": ' + jsonNodes + ', "edges": ' + jsonEdges + '}' # Save file to server cache with open(webserverstatic + 'main.json', "w+") as jsonFile: jsonFile.write(finalJson) jsonFile.close() # Send file to template to display generated graph return render_template('showdata.html', message="main")
def node_to_rela(self, node_object): #节点转关系 relmatch = RelationshipMatcher(self.graph) rela = [] for i in range(len(node_object) - 1): temp = (list( relmatch.match(nodes=(node_object[i]['node'], node_object[i + 1]['node'])))) for j in temp: rela.append(j) return rela
def get_or_create_relationship(start_node, relationship_type, end_node, **properties): created = False matcher = RelationshipMatcher(graph) relationship = matcher.match(nodes=[start_node, end_node], r_type=relationship_type) if not relationship.exists(): created = True relationship = graph.create( Relationship(start_node, relationship_type, end_node, **properties)) return created, relationship
def test_rel_index_cache(self): folder = os.path.dirname(os.path.abspath(__file__)) test_driller = CacheDriller(os.path.join(folder, 'cnfg_simple.yml')) test_driller.drill_batch_cache_sequential() # test that all relationships were indexed rel_matcher = RelationshipMatcher(test_driller.graph) all_branch = list(rel_matcher.match(None, "BranchCommit")) assert len(all_branch) == 8 all_authorship = list(rel_matcher.match(None, "Author")) assert len(all_authorship) == 8 all_parent = list(rel_matcher.match(None, "Parent")) assert len(all_parent) == 8 all_updadedfile = list(rel_matcher.match(None, "UpdateFile")) assert len(all_updadedfile) == 9 all_hasmethod = list(rel_matcher.match(None, "Method")) assert len(all_hasmethod) == 5 all_updatemethod = list(rel_matcher.match(None, "UpdateMethod")) assert len(all_updatemethod) == 9 test_driller.clean()
def AddWalksWithRelathionship(name1, name2): graph = GetGraph() matcher = NodeMatcher(graph) rel_matcher = RelationshipMatcher(graph) tx = graph.begin() t = int(_time.time()) person_1 = matcher.match("Person").where("_.name = '" + name1 + "'").first() person_2 = matcher.match("Person").where("_.name = '" + name2 + "'").first() walks_with = rel_matcher.match(nodes=[person_1, person_2], r_type="WALKS_WITH").first() walks_with_reverse = rel_matcher.match(nodes=[person_2, person_1], r_type="WALKS_WITH").first() # print(walks_with) # print(walks_with_reverse) if walks_with is None: walks_with = Relationship(person_1, "WALKS_WITH", person_2, weight=0, last_time=t) tx.create(walks_with) elif t - walks_with['last_time'] > 60: walks_with['weight'] += 1 walks_with['last_time'] = t tx.push(walks_with) if walks_with_reverse is None: walks_with_reverse = Relationship(person_2, "WALKS_WITH", person_1, weight=0, last_time=t) tx.create(walks_with_reverse) elif t - walks_with_reverse['last_time'] > 60: walks_with_reverse['weight'] += 1 walks_with_reverse['last_time'] = t tx.push(walks_with_reverse) tx.commit()
def test_custom_attributes_rel(self): folder = os.path.dirname(os.path.abspath(__file__)) test_driller = Driller(os.path.join(folder, 'cnfg_simple.yml')) test_driller.drill_batch() node_matcher = NodeMatcher(test_driller.graph) rel_matcher = RelationshipMatcher(test_driller.graph) commit = node_matcher.match( "Commit", hash="aa6fa504ccb0fa919acc3cb31e510dc2048314eb0656f34babada15c" ).first() assert commit['is_merge'] == 0 update_file_rel = rel_matcher.match([commit], "UpdateFile").first() assert update_file_rel['complexity'] == 2 assert update_file_rel['nloc'] == 8 assert update_file_rel['old_path'] == 'gr_test/default_class.py' assert update_file_rel['path'] == 'gr_test/default_class.py' assert update_file_rel['token_count'] == 42 assert update_file_rel['type'] == 'MODIFY' assert update_file_rel['removed'] == 6 assert update_file_rel['added'] == 0 update_method_rel = rel_matcher.match([commit], 'UpdateMethod').first() # assert update_method_rel['type'] == 'DELETE' assert update_method_rel['nloc'] == 5 assert update_method_rel['complexity'] == 2 assert update_method_rel['token_count'] == 21 assert update_method_rel['length'] == 5 assert update_method_rel['fan_in'] == 0 assert update_method_rel['fan_out'] == 0 assert update_method_rel['start_line'] == 11 assert update_method_rel['end_line'] == 15 test_driller.clean()
def dfs(self, *label, **properties): ''' Version 1:dfs 直到没有边为止 doing 有边相连就遍历,除非遍历到函数-ROOT节点,此时不再往上遍历 Version 2:dfs 遍历时候添加条件判断 ''' matcher = NodeMatcher(self.graph) rel_matcher = RelationshipMatcher(self.graph) node = matcher.match(*label, **properties) node_passed = before = list(node) after = list() while before: # 每次进入循环,向外再遍历一层(层次遍历) for now_node in before: rels = rel_matcher.match({now_node}) for rel in rels: start, end = rel.nodes # 此处后面添加,对节点的判断(如到函数根节点时停,节点属性进行判断操作) if start not in node_passed and start.get( "attribute")[-9:] != "java-ROOT": after.append(start) node_passed.append(start) if end not in node_passed: after.append(end) node_passed.append(end) before = after after = list() # 使用字典保存所有出现的标签 all_labels = list() for _ in node_passed: if all_labels: temp = sorted(_.labels) if temp not in all_labels: all_labels.append(temp) else: all_labels.append(sorted(_.labels)) # test all_id = set() for _ in node_passed: all_id.add(_.get("id")) return node_passed, sorted(all_id), all_labels
def get_intent_relations(self): ''' 获取所有意图关系数据: 34 --> 35 意图之间的层级关系 :return: [(34,35),(56,57)] ''' re_matcher = RelationshipMatcher(self.graph) re_list = list(re_matcher.match(r_type='ex_context')) for _r in re_list: name_to_id = [] _re_unit = tuple(re.findall('\((.*?)\)', str(_r))) # 匹配数字 for _name in _re_unit: _id = self.id_to_name[_name] name_to_id.append(str(_id)) _tuple = tuple(name_to_id) self.re_cols.append(_tuple) print("self.re_cols:",self.re_cols) return self.re_cols
def getEntityRels(): type = request.args['type'] entity_name = request.args['name'] # 获取特定的节点 node = NodeMatcher(DB).match(type, name=entity_name).first() # 获取该节点的所有关系 rel_matcher = RelationshipMatcher(DB) rels = rel_matcher.match(nodes=set([node, None])) result = [] for re in rels: result.append({ 'start_node': re.start_node, 'end_node': re.end_node, 'path': str(re), 'attr': dict(re) }) return jsonify(result)
def _createAuthor(pub, names): graph = connectGraph() print(' Creating Authors') for auth in names: matcher = NodeMatcher(graph) aNode = matcher.match("Author", name=auth['name']).first() if aNode is None: aNode = Node('Author', name=auth['name']) path_1 = Path(aNode, 'AUTHORED', pub) graph.create(path_1) else: #Check the relationship rmatcher = RelationshipMatcher(graph) auNode = rmatcher.match((aNode,pub), "AUTHORED").first() if auNode is None: path_1 = Path(aNode, 'AUTHORED', pub) graph.create(path_1)
def _createReferences(pub, references): graph = connectGraph() print(' Creating References') for ref in references: #Find the Paper details matcher = NodeMatcher(graph) pbNode = matcher.match("Paper", id=ref).first() if pbNode == None: #path_1 = Node('PAPER', 'AMINER', name=ref) pbNode = Node('Paper', id=ref) path_1 = Path(pub, 'REFERENCE', pbNode) graph.create(path_1) else: #Check for existing relationship rmatcher = RelationshipMatcher(graph) auNode = rmatcher.match((pbNode, pub), "REFERENCE").first() if auNode is None: path_1 = Path(pub, 'REFERENCE', pbNode) graph.create(path_1)
def count_Selected_User_MENTIONS(id_str): if (Neo4jConnection.Neo4jEntry.graph_neo4j == None): #print("Conect neo4j before with Conect_Neo4j() function.") return None else: try: selector = NodeMatcher(Neo4jConnection.Neo4jEntry.graph_neo4j) user = selector.match("Selected_User", id_str=id_str).first() count = 0 if(user!=None): relationship = RelationshipMatcher(Neo4jConnection.Neo4jEntry.graph_neo4j) rels = relationship.match(r_type="MENTIONS",nodes=(None,user)) for rel in rels: if(rel != None): count = count + 1 return count except Exception as e: print(e) return None
def _createKeywords(pub, keywords): graph = connectGraph() print(' Creating Keywords') for kw in keywords: #Find keywords TODO : Check for duplicate on re-run matcher = NodeMatcher(graph) #pbNode = matcher.match("KEYWORDS", kw.upper(), name=kw.lower()).first() pbNode = matcher.match("Keywords", kw.lower(), name=kw.lower()).first() if pbNode == None: pbNode = Node('Keywords', kw.lower(), name=kw.lower()) path_1 = Path(pub, 'CONTAINS', pbNode) graph.create(path_1) else: #Check for existing relationship rmatcher = RelationshipMatcher(graph) auNode = rmatcher.match((pbNode,pub), "CONTAINS").first() if auNode is None: path_1 = Path(pub, 'CONTAINS', pbNode) graph.create(path_1)
def GetKSP(self, s_label, s_key, s_content, e_label, e_key, e_content, k, weight): cql = ''' MATCH (start:%s{%s:"%s"}), (end:%s{%s:"%s"}) CALL algo.kShortestPaths.stream(start, end, %s, "%s" ,{direction:'OUTGOING', path: true}) YIELD index, nodeIds, costs,path RETURN [node in algo.getNodesById(nodeIds) | node] AS nodes, costs, reduce(acc = 0.0, cost in costs | acc + cost) AS totalCost, path ''' % (s_label, s_key, s_content, e_label, e_key, e_content, k, weight) res = self.graph.run(cql).data() relmatch = RelationshipMatcher(self.graph) rela = [] for i in res: for j in range(len(i['nodes']) - 1): temp = (list( relmatch.match(nodes=(i['nodes'][j], i['nodes'][j + 1])))) for k in temp: rela.append(k) return rela
def GetShortTestPath(self, s_label, s_key, s_content, e_label, e_key, e_content, weight): cql1 = ''' MATCH (start:%s{%s:"%s"}),(end:%s{%s:"%s"}) CALL algo.shortestPath.stream(start, end, "%s") YIELD nodeId,cost WITH nodeId,cost CALL apoc.get.nodes(nodeId) YIELD node RETURN node ''' % (s_label, s_key, s_content, e_label, e_key, e_content, weight) res_node = self.graph.run(cql1).data() relmatch = RelationshipMatcher(self.graph) rela = [] for i in range(len(res_node) - 1): temp = (list( relmatch.match(nodes=(res_node[i]['node'], res_node[i + 1]['node'])))) for j in temp: rela.append(j) return rela
def readGrapy(graph): nodes = [] for i in graph.nodes.match('device'): print(i['name']) node_device = {} node_device['id'] = i['name'] node_device['group'] = 1 nodes.append(node_device) for i in graph.nodes.match('vul'): print(i['name']) node_vul = {} node_vul['id'] = i['name'] node_vul['group'] = 2 nodes.append(node_vul) for i in graph.nodes.match('patch'): print(i['name']) node_patch = {} node_patch['id'] = i['name'] node_patch['group'] = 3 nodes.append(node_patch) links = [] matcher = RelationshipMatcher(graph) for i in matcher.match(): source = i.start_node['name'] target = i.end_node['name'] dict_link = {} dict_link['source'] = source dict_link['target'] = target dict_link['value'] = 1 links.append(dict_link) dict_json = {} dict_json["nodes"] = nodes dict_json["links"] = links saveToJson(dict_json)
def update_user_settings(username, settings): try: # get node of user updating their settings matcher = NodeMatcher(GRAPH) user_node = matcher.match("User", username=username).first() # get relationship matcher rel_matcher = RelationshipMatcher(GRAPH) # find user's settings node rel = rel_matcher.match([user_node, None], 'HAS_SETTINGS').first() settings_node = rel.end_node for setting in settings: settings_node[setting] = settings[setting] GRAPH.push(settings_node) return str(True) except Exception as e: print(e) return str(False)
def search(): # 完善一下的话,html的地方写个循环 if request.method == 'POST': information = request.form.get("information") graph = Graph('http://localhost:7474', username='******', password='******') matcher = NodeMatcher(graph) nodelist = list(matcher.match()) numlist1 = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh'] numlist2 = ['one', 'two', 'three', 'four'] nodedict = dict(zip(numlist1, nodelist)) relmatch = RelationshipMatcher(graph) relist = list(relmatch.match()) reldict = dict(zip(numlist2, relist)) # nodedict1 = json.dumps(nodedict, encoding='UTF-8', ensure_ascii=False) # reldict1 = json.dumps(reldict, encoding='UTF-8', ensure_ascii=False) return render_template('index.html', **nodedict, **reldict) return render_template('search.html')
class graphDB_interface: def __init__(self): config_str = ''.join(open(CFG_FILE).readlines()).replace('\n', ' ') config = json.loads(config_str) self.graph = Graph(config['url'], name=config['name'], password=config['password']) self.nodematcher = NodeMatcher(self.graph) self.relmatcher = RelationshipMatcher(self.graph) def fuzzySearchNode(self, labels, attrs, fuzzymatcher=fuzzyMatchStr, mode=0): ''' mode = 0, confident on labels (though maybe partial), allow fuzzy matching for attrs ''' if isinstance(labels, str): labels = [labels] candidates = [] for node in self.nodematcher.match(*labels): for key, value in attrs.items(): v = node[key] match = v == value if fuzzymatcher is None else fuzzymatcher( v, value) if match: candidates.append(node) return candidates def fuzzySearchRels(self, label1, attrs1, label2, attrs2, rtype): pass def searchNode(self, labels, attrs): if isinstance(labels, str): labels = [labels] name = '_.name=' + '\'' + attrs['name'] + '\'' node = self.nodematcher.match(*labels).where(name).first() # for index in graphDB.graph.nodes: # node = graphDB.graph.nodes[index] # print(node.labels, node.keys()) return node def createNode(self, labels, attrs): if isinstance(labels, str): labels = [labels] node = self.searchNode(labels, attrs) if node is None: node = Node(*labels, **attrs) self.graph.create(node) return True print('node {} is already exists.'.format(attrs)) return False def searchRel_onhead(self, label, attrs, rtype): node = self.searchNode(label, attrs) if node is None: print( 'node {} does not exists. Search relation from it returns nothing.' .format(attrs)) return None rel = self.relmatcher.match((node, None), rtype).first() return rel def searchRel_ontail(self, label, attrs, rtype): node = self.searchNode(label, attrs) if node is None: print( 'node {} does not exists. Search relation to it returns nothing.' .format(attrs)) return None rel = self.relmatcher.match((None, node), rtype).first() return rel def searchRel(self, label1, attrs1, label2, attrs2, rtype): node1 = self.searchNode(label1, attrs1) node2 = self.searchNode(label1, attrs1) if node1 is None or node2 is None: print( 'node {} or {} does not exists. Search relation between them returns nothing' .format(attrs1, attrs2)) return None rel = self.relmatcher.match((node1, node2), rtype).first() return rel def createRel(self, label1, attrs1, label2, attrs2, rtype): node1 = self.searchNode(label1, attrs1) node2 = self.searchNode(label2, attrs2) if node1 is None or node2 is None: print('node {} or {} does not exists. Please create them first.'. format(attrs1, attrs2)) return False rel = self.searchRel(label1, attrs1, label2, attrs2, rtype) if rel is not None: print('relation {} is already exists.'.format(rel)) return False rel = Relationship(node1, rtype, node2) self.graph.create(rel) return True def empty(self): self.graph.delete_all()
class GotGraph(object): """ This object provides a set of helper methods for creating and retrieving nodes and relationships from a Neo4j database holding information about players, teams, fans, comments and their relationships. """ # Note: # I tend to avoid object mapping frameworks. Object mapping frameworks are fun in the beginning # but tend to be annoying after a while. So, I did not create types Player, Team, etc. # # Connects to the DB and sets a Graph instance variable. # Also creates a NodeMatcher and RelationshipMatcher, which are a py2neo framework classes. def __init__( self, auth=('neo4j', 'dbuserdbuser'), host='localhost', port=7687, secure=False, ): self._graph = Graph(secure=secure, bolt=True, auth=auth, host=host, port=port) self._node_matcher = NodeMatcher(self._graph) self._relationship_matcher = RelationshipMatcher(self._graph) def run_q(self, qs, args): """ :param qs: Query string that may have {} slots for parameters. :param args: Dictionary of parameters to insert into query string. :return: Result of the query, which executes as a single, standalone transaction. """ try: tx = self._graph.begin(autocommit=False) result = self._graph.run(qs, args) return result except Exception as e: print("Run exaception = ", e) def run_match(self, labels=None, properties=None): """ Uses a NodeMatcher to find a node matching a "template." :param labels: A list of labels that the node must have. :param properties: A dictionary of {property_name: property_value} defining the template that the node must match. :return: An array of Node objects matching the pattern. """ #ut.debug_message("Labels = ", labels) #ut.debug_message("Properties = ", json.dumps(properties)) if labels is not None and properties is not None: result = self._node_matcher.match(labels, **properties) elif labels is not None and properties is None: result = self._node_matcher.match(labels) elif labels is None and properties is not None: result = self._node_matcher.match(**properties) else: raise ValueError( "Invalid request. Labels and properties cannot both be None.") # Convert NodeMatch data into a simple list of Nodes. full_result = [] for r in result: full_result.append(r) return full_result def find_nodes_by_template(self, tmp): """ :param tmp: A template defining the label and properties for Nodes to return. An example is { "label": "Fan", "template" { "last_name": "Ferguson", "first_name": "Donald" }} :return: A list of Nodes matching the template. """ labels = tmp.get('label', None) props = tmp.get("template", None) result = self.run_match(labels=labels, properties=props) return result def create_node(self, label, **kwargs): n = Node(label, **kwargs) tx = self._graph.begin(autocommit=True) tx.create(n) return n # Given a UNI, return the node for the Fan. def get_character(self, character_id): n = self.find_nodes_by_template({ "label": "Character", "template": { "character_id": character_id } }) if n is not None and len(n) > 0: # I should throw an exception here if there is more than 1. n = n[0] else: n = None return n def get_related_characters(self, ch_id, r_kind): t = self.get_character(ch_id.upper()) nodes = set() nodes.add(t) n = self._relationship_matcher.match(nodes, r_type=r_kind.upper()) return n def create_character_relationship(self, source_id, target_id, label): """ Create a SUPPORTS relationship from a Fan to a Team. :param uni: The UNI for a fan. :param team_id: An ID for a team. :return: The created SUPPORTS relationship from the Fan to the Team """ f = self.get_character(source_id) t = self.get_character(target_id) l = label.upper() r = Relationship(f, l, t) tx = self._graph.begin(autocommit=True) tx.create(r) return r def get_appearance(self, player_id, team_id, year_id): """ Get the information about appearances for a player and team. :param player_id: player_id :param team_id: team_id :param year_id: The year for getting appearances. :return: """ try: # Get the Nodes at the ends of the relationship representing appearances. p = self.get_player(player_id) t = self.get_team(team_id) # Run a match looking for relationships of a specific type linking the nodes. rm = self._graph.match(nodes=[p, t], r_type="APPEARED") result = [] # If there is a list of relationships. if rm is not None: for r in rm: # The type will be a class APPEARED() because of the OO mapping. node_type = type(r).__name__ year = r['year'] # If the type and year are correct, add to result if node_type == "APPEARED" and (year == year_id or year_id is None): result.append(r) return result else: return None except Exception as e: print("get_appearance: Exception e = ", e) raise e # Create an APPEARED relationship from a player to a Team def create_appearance_all(self, player_id, team_id, year, games): """ :param player_id: O :param team_id: :param year: :param games: :return: """ try: tx = self._graph.begin(autocommit=False) q = "match (n:Player {player_id: '" + player_id + "'}), " + \ "(t:Team {team_id: '" + team_id + "'}) " + \ "create (n)-[r:APPEARED { games: " + str(games) + ", year : " + str(year) + \ "}]->(t)" result = self._graph.run(q) tx.commit() except Exception as e: print("create_appearances: exception = ", e) # Create a FOLLOWS relationship from a Fan to another Fan. def create_follows(self, follower, followed): f = self.get_fan(follower) t = self.get_fan(followed) r = Relationship(f, "FOLLOWS", t) tx = self._graph.begin(autocommit=True) tx.create(r) def get_comment(self, comment_id): """ :param comment_id: Comment ID :return: Comment """ n = self.find_nodes_by_template({ "label": "Comment", "template": { "comment_id": comment_id } }) if n is not None and len(n) > 0: n = n[0] else: n = None return n def create_comment(self, uni, comment, team_id=None, player_id=None): """ Creates a comment :param uni: The UNI for the Fan making the comment. :param comment: A simple string. :param team_id: A valid team ID or None. team_id and player_id cannot BOTH be None. :param player_id: A valid player ID or None :return: The Node representing the comment. """ if uni is None or comment is None or (player_id is None and team_id is None): raise ValueError("create_comment: invalid input.") comment_id = str( uuid.uuid4()) # Generate a UUID. Will explain in class. fan = None team = None player = None tx = None try: tx = self._graph.begin( ) # We are going to make a transactional update. fan = self.get_fan(uni) # Get the node for the Fan. if fan is None: raise ValueError("create_comment: Fan node node found.") if team_id is not None: team = self.get_team(team_id) if team is None: raise ValueError("create_comment: Team node node found.") if player_id is not None: player = self.get_player(player_id) if player is None: raise ValueError("create_comment: Player node node found.") c = Node("Comment", comment_id=comment_id, comment=comment) tx.create(c) pc = Relationship(fan, "COMMENT_BY", c) tx.create(pc) if player is not None: pr = Relationship(c, "COMMENT_ON", player) tx.create(pr) if team is not None: p2 = Relationship(c, "COMMENT_ON", team) tx.create(p2) tx.commit() return c except Exception as e: if tx: tx.rollback() raise RuntimeError( "create_comment: Something evil happened., e = " + str(e)) def create_sub_comment(self, uni, origin_comment_id, comment): """ Create a sub-comment (response to a comment or response) and links with parent in thread. :param uni: ID of the Fan making the comment. :param origin_comment_id: Id of the comment to which this is a response. :param comment: Comment string :return: Created comment. """ if uni is None or origin_comment_id is None or comment is None: raise ValueError("create_sub_comment: invalid input.") comment_id = str( uuid.uuid4()) # Generate a UUID. Will explain in class. fan = None origin_comment = None tx = None try: tx = self._graph.begin( ) # We are going to make a transactional update. fan = self.get_fan(uni) # Get the node for the Fan. if fan is None: raise ValueError("create_sub_comment: Fan node node found.") origin_comment = self.get_comment(origin_comment_id) if origin_comment is None: raise ValueError( "create_sub_comment: Original comment node not found.") c = Node("Comment", comment_id=comment_id, comment=comment) tx.create(c) sc = Relationship(c, "RESPONSE_TO", origin_comment) tx.create(sc) pc = Relationship(fan, "RESPONSE_BY", c) tx.create(pc) tx.commit() except Exception as e: if tx: tx.rollback() raise RuntimeError( "create_comment: Something evil happened., e = " + str(e)) def get_sub_comments(self, comment_id): """ :param comment_id: The unique ID of the comment. :return: The sub-comments. """ q = "match (c:Comment {comment_id: {cid}})<-[response:RESPONSE_TO]-(sc:Comment) return sc,response,c" c = self._graph.run(q, cid=comment_id) return c def get_roster(self, team_id, year_id): q = "match (t:Team {team_id: {tid}})<-[a:APPEARED {year: {yid}}]-(p:Player) " + \ " return t.team_id, t.team_name, a.year, a.games, p.player_id, p.last_name, p.first_name" c = self._graph.run(q, tid=team_id, yid=year_id) return c def get_player_comments(self, player_id): """ Gets all of the comments associated with a player, all of the comments on the comment and comments on the comments, etc. Also returns the Nodes for people making the comments. :param player_id: ID of the player. :return: Graph containing comment, comment streams and commenters. """ q = 'match (fan)-[by:COMMENT_BY]->(comment)-[on:COMMENT_ON]->(player:Player {player_id: {pid}}) ' + \ 'return fan.uni, fan.last_name, fan.first_name, comment.comment_id, comment.comment, ' + \ " player.player_id, player.last_name, player.first_name " result = self._graph.run(q, pid=player_id) return result def get_player_comments_g(self, player_id): """ Gets all of the comments associated with a player, all of the comments on the comment and comments on the comments, etc. Also returns the Nodes for people making the comments. :param player_id: ID of the player. :return: Graph containing comment, comment streams and commenters. """ q = 'match (fan)-[by:COMMENT_BY]->(comment)-[on:COMMENT_ON]->(player:Player {player_id: {pid}}) ' + \ 'return fan, by, comment, on, player ' result = self._graph.run(q, pid=player_id) return result def get_team_comments(self, team_id): """ Gets all of the comments associated with a teams, all of the comments on the comment and comments on the comments, etc. Also returns the Nodes for people making the comments. :param player_id: ID of the team. :return: Graph containing comment, comment streams and commenters. """ t = self.get_team(team_id) nodes = set() nodes.add(t) n = self._relationship_matcher.match(nodes, r_type="COMMENT_ON") return n def get_players_by_team(self, team_id): """ :param team_id: Team ID :return: List of Nodes representing players who played for the team. """ q = "match (p:Player)-[r:APPEARED]->(t:Team) where t.team_id={tid} return p,r,t" result = self._graph.run(q, tid=team_id) result = result.data() ans = [] for r in result: current = dict(r['p'].items()) current['year'] = r['r']['year'] ans.append(current) return ans
def find_dep_node(MDG, matcher, dep): if len(dep) != 3: return (None, "the dependency is malformed!") # Remember, we fiddled with dep so dep[2] is not quite version version, needs_match = dep[2] v = version # If it needs a match, there are two trailing characters at the end if needs_match: v = version[:-2] found_nodes = matcher.match("Artifact", groupID=dep[0], artifact=dep[1], version=v) # If we can't find the node, we add it to the MDG if len(found_nodes) == 0: tx = MDG.begin() dep_node = Node("Artifact", groupID=dep[0], artifact=dep[1], version=version, coordinates=dep[0] + ":" + dep[1] + ":" + v) tx.create(dep_node) tx.commit() # If we need a match, this is not the node we're looking for # and we can't really find the one we're looking for # so we simply add it to the exceptions if needs_match: return (None, "finding the dependency requires a" + " node match that is impossible!") else: return (dep_node, "") elif len(found_nodes) > 1: return (None, "multiple nodes with the same Maven coordinates!") found_node = found_nodes.first() # Otherwise, we found the node. If we need a match if needs_match: r_matcher = RelationshipMatcher(MDG) # Either we need the version immediately preceding or # immediately following the current node. # In both cases, if we can't find the relationship, we can't do much # If we do, we return the corresponding node # NB: the "None" in nodes mean "any node" if version[-1] == 'm': found_rs = r_matcher.match(nodes=(None, found_node), r_type="NEXT") found_r = found_rs.first() if found_r is None: return ( None, "finding the dependency requires a relationship match that is impossible!" ) return (found_r.start_node, "") else: found_rs = r_matcher.match(nodes=(found_node, None), r_type="NEXT") found_r = found_rs.first() if found_r is None: return (None, "finding the dependency requires" + "a relationship match that is impossible!") return (found_r.end_node, "") else: return (found_node, "")
def returnDoF(): person = request.args.get('person') # Connect to database graph = Graph("http://*****:*****@localhost:7474") nodematcher = NodeMatcher(graph) relamatcher = RelationshipMatcher(graph) nodes = [] edges = [] # Find the node for the person selected personNode = nodematcher.match("COSTAR", name=person).first() # Convert node to GraphJSON nodes.append({ "id": personNode.identity, "name": personNode["name"], "rta": personNode["rta"], "tp": personNode["tp"], "ao": personNode["ao"] }) # Find all relationships for the selected person ships1 = relamatcher.match((personNode, None)) ships2 = relamatcher.match((None, personNode)) # Convert the relationships and nodes to GraphJSON for ship in ships1: nodes.append({ "id": ship.end_node.identity, "name": ship.end_node["name"], "rta": ship.end_node["rta"], "tp": ship.end_node["tp"], "ao": ship.end_node["ao"] }) edges.append({ "source": ship.start_node.identity, "target": ship.end_node.identity, "role": "appeared_with" }) for ship in ships2: nodes.append({ "id": ship.start_node.identity, "name": ship.start_node["name"], "rta": ship.start_node["rta"], "tp": ship.start_node["tp"], "ao": ship.start_node["ao"] }) edges.append({ "source": ship.start_node.identity, "target": ship.end_node.identity, "role": "appeared_with" }) jsonNodes = dumps(nodes) jsonEdges = dumps(edges) # Create a final json file with all GraphJSON finalJson = '{"nodes": ' + jsonNodes + ', "edges": ' + jsonEdges + '}' # Save file to server cache fileLocation = (webserverstatic + person + '.json').encode("utf-8") with open(fileLocation, "w+") as test: test.write(finalJson) # Send file to template to display generated graph return render_template('showdata.html', message=person)
# 创建节点(均可直接赋值变量) a = Node('User', name='yaim') #第1个参数为节点类型,第2个参数为节点属性和值 b = Node('User', name='fyl') # 创建关系 r = Relationship(a, 'SAME', b) # 将节点和关系加入到数据库 s = a | b | r graph.create(s) #查询节点 print(graph.nodes[0]) #根据节点id,返回节点 print(graph.nodes.get(0)) #同上 print(list(graph.nodes.match('User'))) #根据条件,返回节点列表 print(graph.nodes.match('User', name='yaim').first()) #根据条件,返回第1个节点 # 查询关系 rel_matcher = RelationshipMatcher(graph) rel_all = list(rel_matcher.match()) #获取所有关系,返回列表 rel_this = list(rel_matcher.match(r_type='SAME')) #获取某一关系,返回列表 # 删除节点 node_del = graph.nodes.match('User', name='temp').first() #先查询到某一个节点 graph.delete(node_del) #再删除 # ***删除关系 rel_del = rel_matcher.match(r_type='SAME').first() #先查询到某一个关系 graph.delete(rel_del) #再删除,*连带删除节点?* # 更新节点 node_update = graph.nodes.match('User', name='yaim').first() #先查询到某一个节点 node_update['name'] = 'yaim_new' #更新该节点某一属性值 graph.push(node_update) #提交更新 # ***更新关系