def get_graph(self, request, **kwargs): self.method_check(request, allowed=['get']) self.throttle_check(request) depth = int(request.GET['depth']) if 'depth' in request.GET.keys() else 1 aggregation_threshold = 10 ### # First we retrieve every leaf in the graph query = """ START root=node({root}) MATCH p = (root)-[*1..{depth}]-(leaf)<-[:`<<INSTANCE>>`]-(type) WHERE HAS(leaf.name) AND type.app_label = '{app_label}' AND length(filter(r in relationships(p) : type(r) = "<<INSTANCE>>")) = 1 RETURN leaf, ID(leaf) as id_leaf, type """.format(root=kwargs['pk'], depth=depth, app_label=get_model_topic(self.get_model())) rows = connection.cypher(query).to_dicts() leafs = {} # We need to retrieve the root in another request # TODO : enhance that query = """ START root=node({root}) MATCH (root)<-[:`<<INSTANCE>>`]-(type) RETURN root as leaf, ID(root) as id_leaf, type """.format(root=kwargs['pk']) for row in connection.cypher(query).to_dicts(): rows.append(row) for row in rows: row['leaf']['data']['_id'] = row['id_leaf'] row['leaf']['data']['_type'] = row['type']['data']['model_name'] leafs[row['id_leaf']] = row['leaf']['data'] # ### ### # Then we retrieve all edges query = """ START A=node({leafs}) MATCH (A)-[rel]->(B) WHERE type(rel) <> "<<INSTANCE>>" RETURN ID(A) as head, type(rel) as relation, id(B) as tail """.format(leafs=','.join([str(id) for id in leafs.keys()])) rows = connection.cypher(query).to_dicts() edges = [] for row in rows: try: if (leafs[row['head']] and leafs[row['tail']]): edges.append([row['head'], row['relation'], row['tail']]) except KeyError: pass # ### self.log_throttled_access(request) return self.create_response(request, {'leafs': leafs, 'edges' : edges})
def get_graph(self, request, **kwargs): self.method_check(request, allowed=["get"]) self.throttle_check(request) depth = int(request.GET["depth"]) if "depth" in request.GET.keys() else 1 topic = Topic.objects.get(ontology_as_mod=get_model_topic(self.get_model())) leafs, edges = get_leafs_and_edges(topic=topic, depth=depth, root_node=kwargs["pk"]) self.log_throttled_access(request) return self.create_response(request, {"leafs": leafs, "edges": edges})
def get_graph(self, request, **kwargs): self.method_check(request, allowed=['get']) self.throttle_check(request) depth = int(request.GET['depth']) if 'depth' in request.GET.keys() else 2 topic = Topic.objects.get(ontology_as_mod=get_model_topic(self.get_model())) leafs, edges = get_leafs_and_edges( topic = topic, depth = depth, root_node = kwargs['pk']) self.log_throttled_access(request) return self.create_response(request, {'leafs': leafs, 'edges' : edges})
def get_topic(self, bundle=None): model = self.get_model() topic = None # Bundle given if bundle != None: # The topic may be set by a middleware topic = get_topic_from_request(bundle.request) # No topic found if topic == None: # We found the topic according to the current model topic = Topic.objects.get(ontology_as_mod=get_model_topic(model)) return topic
def get_topic_from_bundle(self, bundle): topic = get_topic_from_request(bundle.request) if topic == None: topic = Topic.objects.get(ontology_as_mod=get_model_topic(bundle.obj)).public return topic
def reduce_origin(rows): # No nodes, no links if len(rows) == 0: return ([], [],) # Initialize structures all_nodes = dict() # Use defaultdict() to create somewhat of an autovivificating list # We want to build a structure of the form: # { source_id : { relation_name : [ target_ids ] } } # Must use a set() instead of list() to avoid checking duplicates but it screw up json.dumps() all_links = defaultdict(lambda: dict(__count=0, __relations=defaultdict(list))) IDs = set(sum([row['nodes'] for row in rows], [])) # Get all entities from their IDs query = """ START root = node({0}) MATCH (root)-[:`<<INSTANCE>>`]-(type) WHERE type.app_label = '{1}' AND HAS(root.name) RETURN ID(root) as ID, root, type """.format(','.join([str(ID) for ID in IDs]), get_model_topic(self.get_model())) all_raw_nodes = connection.cypher(query).to_dicts() for row in all_raw_nodes: # Twist some data in the entity for key in row['root']['data'].keys(): if key[0] == '_': del row['root']['data'][key] row['root']['data']['_type'] = row['type']['data']['model_name'] row['root']['data']['_id'] = row['ID'] all_nodes[row['ID']] = row['root']['data'] for row in rows: nodes = row['nodes'] i = 0 for relation in row['relations']: try: if all_nodes[nodes[i]] is None or all_nodes[nodes[i + 1]] is None: continue (a, b) = (nodes[i], nodes[i + 1]) if re.search('^'+to_underscores(all_nodes[nodes[i]]['_type']), relation) is None: (a, b) = (nodes[i + 1], nodes[i]) if not b in all_links[a]['__relations'][relation]: all_links[a]['__count'] += 1 all_links[a]['__relations'][relation].append(b) except KeyError: pass i += 1 # Sort and aggregate nodes when we're over the threshold for node in all_links.keys(): shortcut = all_links[node]['__relations'] if all_links[node]['__count'] >= aggregation_threshold: sorted_relations = sorted([(len(shortcut[rel]), rel) for rel in shortcut], key=lambda to_sort: to_sort[0]) shortcut = defaultdict(list) i = 0 while i < aggregation_threshold: for rel in sorted_relations: try: node_id = all_links[node]['__relations'][rel[1]].pop() shortcut[rel[1]].append(node_id) i += 1 except IndexError: # Must except IndexError if we .pop() on an empty list pass if i >= aggregation_threshold: break shortcut['_AGGREGATION_'] = sum(all_links[node]['__relations'].values(), []) all_links[node] = shortcut return (all_nodes, all_links)
def read_detail(self, object_list, bundle): if not Topic.objects.get(ontology_as_mod=get_model_topic(bundle.obj)).public and not self.check_contribution_permission(object_list, bundle, 'read'): raise Unauthorized("Sorry, only staff or contributors can read resource.") return True