def shortestPathWeight(query, rootNode): stop = stopwords.words('english') query = query.split() g = Graph() weight = 0 for term in query: pathSet = set() if term not in stop: result = g.cypher.execute("MATCH (n:NP) where str(n.phrase) =~ '(?i).*"+term+".*' return n") if result: for item in result: uri = item.n.graph.uri + item.n.ref + '/path' headers = { 'Accept': 'application/json', 'Content-Type': 'application/json; charset=UTF-8' } target = urlparse(uri.string) method = 'POST' body = { "to": str(rootNode.graph.uri+rootNode.ref), "max_depth": 20, "relationships" : { "type" : "DEPENDS" }, "algorithm" : "shortestPath" } body = json.dumps(body) h = http.Http() response, content = h.request(target.geturl(), method, body, headers) try: data = json.loads(content.decode()) relationships = data['relationships'] for rel in relationships: relId = rel[rel.rfind('/')+1:] rel = g.relationship(relId) pathSet.add(rel.properties['path_id']) weight = weight + harmonicProduct(len(pathSet)) except: pass return weight
class GraphDB: def __init__(self,username, password, server, port): ''' username = '******' password = '******' server = 'localhost' port = '7474' ''' self.username = username self.password = password self.server = server self.port = port self.con_url = 'http://'+username+':'+password+'@'+server+':'+port+'/db/data/' self.graph = Graph(self.con_url) ##TODO: move these to constants.py when IPYTHON not required self.metaprops = { 'RESOLVEDUUID':'_resolvedWithUUID_', 'RESOLVEDRELID':'_resolvedWithRELID_', 'RESOLVEDHENID':'_resolvedWithHENID_', ##for hyper edge node 'RESOLVEDHERID':'_resolvedWithHERID_', ##for hyper edge relation } #Done: Multiple each time want to ask something #Else: works on old data only ##Wont use this def getGraph(self): return self.graph ##NOT TO BE USED #this is how we use the intenal ids of the graph ##should we use it?? most people say no ## anyways, made the method for future use ## Use : getNodeByInternalId(graph, 152) def getNodeByInternalId(self,id): a = self.graph.node(id) #getting by id given internally by neo4j a.pull() return a ##NOT TO BE USED ## similar to above ## Use : getRelByInternalId(graph, 4) def getRelByInternalId(self,id): a = self.graph.relationship(id) a.pull() return a def getNodeByUniqueID(self, uniquelabel, idName, idVal, isIDString=False): ##TODO: move uuid to props query = "match (n:"+uniquelabel+" {" if isIDString: query = query+ idName+":'"+str(idVal)+"'}) return n" else: query = query+ idName+":"+str(idVal)+"}) return n" rc = self.graph.cypher.execute(query) return rc[0][0] def getRelationByUniqueID(self, idName, idVal, isIDString=False): ##TODO: move uuid to props query = "match ()-[r {" if isIDString: query = query+ idName+":'"+str(idVal)+"'}]->() return r" else: query = query+ idName+":"+str(idVal)+"}]->() return r" rc = self.graph.cypher.execute(query) return rc[0][0] def isPropList(self, node, prop): return type(node[prop]) is list ##has a counter brother in nexusapis flask app def isValidNonMetaProp(self, propname): if propname[0]=='_' or propname[-1]=='_': return False return True ##copy meta = True def copyNode(self, node, copymeta = True, exceptions = []): #exceptions are the props that should be included no matter what, if they have underscore or not! naya = Node() for label in node.labels: naya.labels.add(label) for prop in exceptions: if prop in node.properties: naya[prop] = node[prop] for prop in node.properties: if not copymeta: if self.isValidNonMetaProp(prop): naya[prop] = node[prop] else: naya[prop] = node[prop] return naya def copyNodeAsItIs(self, node): return self.copyNode(node) # naya = Node() # for label in node.labels: # naya.labels.add(label) # for prop in node.properties: # naya[prop] = node[prop] # return naya def copyNodeWithoutMeta(self, node, exceptions=[]): return self.copyNode(node, copymeta = False, exceptions = exceptions) def copyRelation(self, rel, copymeta = True, rel_exceptions = [], node_exceptions = []): start_node = '' end_node = '' if not copymeta: start_node = self.copyNodeWithoutMeta(rel.start_node, exceptions = node_exceptions) end_node = self.copyNodeWithoutMeta(rel.end_node, exceptions = node_exceptions) else: start_node = self.copyNodeAsItIs(rel.start_node) end_node = self.copyNodeAsItIs(rel.end_node) reltype = rel.type nayarel = Relationship(start_node, reltype, end_node) for prop in rel_exceptions: if prop in rel.properties: nayarel[prop] = rel[prop] for prop in rel.properties: if not copymeta: if self.isValidNonMetaProp(prop): nayarel[prop] = rel[prop] else: nayarel[prop] = rel[prop] return nayarel def copyRelationAsItIs(self, rel): return self.copyRelation(rel) # start_node = g.copyNodeAsItIs(rel.start_node) # end_node = g.copyNodeAsItIs(rel.end_node) # reltype = rel.type # naya = Relationship(start_node, reltype, end_node) # for prop in rel.properties: # naya[prop] = rel[prop] # return naya def copyObjectAsItIs(self, kind, obj): if kind == 'relation': return self.copyRelationAsItIs(obj) if kind == 'node': return self.copyNodeAsItIs(obj) return None def copyRelationWithoutMeta(self, rel, rel_exceptions = [], node_exceptions = []): return self.copyRelation(rel, copymeta = False, rel_exceptions = rel_exceptions, node_exceptions = node_exceptions) def getDirectlyConnectedEntities(self, idname, idval, uniquelabel='', isIDString = True): ''' given idname like uuid, henid and uniquelabel like entity or hyperedgenode gives us the connected nodes of this node returns nodes which have uuids only note: works for hyperedgenodes only for now #TODO: extend so that this info can be shown on view page ''' from app.constants import LABEL_ENTITY invertedComma = '' if isIDString: invertedComma = "'" query = "match (n:%s {%s:%s%s%s})-[]-(p:%s) return distinct(p)" query = query %(uniquelabel, idname, invertedComma, idval, invertedComma, LABEL_ENTITY) results = self.graph.cypher.execute(query) enlist = [] for res in results: enlist.append(res[0]) return enlist def getDirectlyConnectedRelations(self, idname, idval, uniquelabel='', isIDString = True,outgoing=True): ''' given idname like uuid, henid and uniquelabel like entity or hyperedgenode gives us the connected nodes of this node returns nodes which have uuids only note: works for hyperedgenodes only for now #TODO: extend so that this info can be shown on view page ''' from app.constants import LABEL_ENTITY invertedComma = '' if isIDString: invertedComma = "'" query = '' if outgoing: query = "match (n:%s {%s:%s%s%s})-[p]->(:%s) return distinct(p)" else: query = "match (n:%s {%s:%s%s%s})<-[p]-(:%s) return distinct(p)" query = query %(uniquelabel, idname, invertedComma, idval, invertedComma, LABEL_ENTITY) results = self.graph.cypher.execute(query) rellist = [] for res in results: rellist.append(res[0]) return rellist ##example of some text input: (n154346:businessperson:person:politician {name:"Anita",uuid:1234}) ##Usage: deserializeNode('''(n154346:businessperson:person:politician {name:"Anita",uuid:1234})''') def deserializeNode(self, nodeText): pos = nodeText.find(' ') #get the labels in a set startText = nodeText[1:pos] allLabels = startText.split(':')[1:] allLabels = set(allLabels) #set is imp #get the props in a dict endText = nodeText[pos+1:-1] endTextWB = endText[1:-1] #print endText #print endTextWB propList = endTextWB.split(",") propsDict = {} for x in propList: propval = x.split(":") #for handling the single inverted comma problem prop = propval[0] val = propval[1] if val[0]=="'" and val[-1]=="'": val=val[1:-1] #for handling the double inverted comma problem if val[0]=='"' and val[-1]=='"': val=val[1:-1] propsDict[prop]=val #print propsDict #creating the node from parsedText node = Node() for x in allLabels: node.labels.add(x) for x in propsDict: node[x] = propsDict[x] print node return node ##MAJOR TODO: ##work to do add a form where they can create a node #get a node's page by uuid #also get node's relations in form of graph, embed that graph #edit a node #edit a relation #dlete a node #delete a relation #moderate any change --> how to do that --> where will this lie! #Note the diff between now and then def generateSearchData(self, idname, idval, isIDString, getList=False): from app.utils.commonutils import Utils comp = self.getNodeByUniqueID('entity', idname, idval, isIDString) ##comp is the node in question keywords = '' labels = '' aliases_to_return = '' if getList: keywords = [] labels = [] aliases_to_return = [] quotes = "" ##the ' wre reudundant from beginning for prop in comp.properties: ##begins with underscore ignore if prop!='uuid' and prop!='aliases' and prop[0]!='_': currvalue = str(comp.properties[prop]) currvalue = Utils.processString(currvalue) if prop!='uuid' and len(currvalue)>3: if not getList: keywords = keywords + quotes +currvalue + quotes+"," else: keywords.append(currvalue) neighbours = self.getDirectlyConnectedEntities(idname, idval, 'entity', isIDString) for rel in neighbours: currvalue = str(rel.properties['name']) currvalue = Utils.processString(currvalue) if not getList: keywords = keywords + quotes +currvalue + quotes+"," else: keywords.append(rel.properties['name']) # keywords = keywords + '"' # labels = '' for label in list(comp.labels): if not getList: labels = labels + quotes + label + quotes+"," else: labels.append(label) # labels=labels + '"' aliases = [] if aliases is None or aliases == []: aliases = [comp['name']] ##patch from app.utils.commonutils import Utils aliases = Utils.merge(comp['aliases'],comp['name']) print 'allllllllllllllaaaaaaaa' print aliases # if type(aliases) is not list: ##fix for just one aliases, though wont be req # aliases = [aliases] # ##patch for alias in aliases: if not getList: aliases_to_return = aliases_to_return + quotes +str(Utils.processString(alias)) + quotes+"," else: aliases_to_return.append(alias) # aliases =aliases_to_return + '"' # name = '"'+comp.properties['name']+'"' name = comp.properties['name'] print 'aliases_to_return, aliases, aliases_to_return' print aliases_to_return print keywords if len(keywords)>50: keywords=keywords[:50] return name, labels, aliases_to_return, keywords