Ejemplo n.º 1
0
    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})
Ejemplo n.º 2
0
 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})
Ejemplo n.º 3
0
 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})
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
 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
Ejemplo n.º 6
0
        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)
Ejemplo n.º 7
0
 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