def transform_for_linked_data(edge): """ Modify an edge (assertion) in place to contain values that are appropriate for a Linked Data API. Although this code isn't actually responsible for what an API returns (see the conceptnet-web repository for that), it helps to deal with what edge dictionaries should contain here. The relevant changes are: - Remove the 'features' list - Rename 'uri' to '@id' - Make 'start', 'end', and 'rel' into dictionaries with an '@id' and 'label', removing the separate 'surfaceStart' and 'surfaceEnd' attributes - All dictionaries should have an '@id'. For the edge itself, it's the URI. Without this, we get RDF blank nodes, which are awful. - Set '@type' on objects representing edges and sources. (Nodes get their @type from the `ld_node` function.) """ if 'features' in edge: del edge['features'] for source in edge['sources']: conj = conjunction_uri(*sorted(source.values())) source['@id'] = conj source['@type'] = 'Source' edge['@id'] = edge['uri'] del edge['uri'] edge['@type'] = 'Edge' start_uri = edge['start'] end_uri = edge['end'] rel_uri = edge['rel'] start_label = edge.get('surfaceStart') end_label = edge.get('surfaceEnd') del edge['surfaceStart'] del edge['surfaceEnd'] edge['start'] = ld_node(start_uri, start_label) edge['end'] = ld_node(end_uri, end_label) edge['rel'] = ld_node(rel_uri, None) if 'other' in edge: # TODO: Find out when we use this, or remove it if we don't use it if edge['other'] == start_uri: edge['other'] = edge['start'] elif edge['other'] == end_uri: edge['other'] = edge['end'] else: edge['rel'] = ld_node(rel_uri, None) return edge
def lookup_grouped_by_feature(term, filters=None, scan_limit=1000, group_limit=10): """ Given a query for a concept, return assertions about that concept grouped by their features (for example, "A dog wants to ..." could be a group). It will scan up to `scan_limit` assertions to find out which features exist, then retrieve `group_limit` assertions for each feature if possible. """ if not term.startswith('/c/'): return error( {}, 400, 'Only concept nodes (starting with /c/) can be grouped by feature.' ) found = FINDER.lookup_grouped_by_feature(term) grouped = [] for groupkey, assertions in found.items(): direction, rel = groupkey base_url = '/query' feature_pairs = groupkey_to_pairs(groupkey, term) url = make_query_url(base_url, feature_pairs) symmetric = direction == 0 group = { '@id': url, 'weight': sum(assertion['weight'] for assertion in assertions), 'feature': dict(feature_pairs), 'edges': assertions[:MAX_GROUP_SIZE], 'symmetric': symmetric } if len(assertions) > MAX_GROUP_SIZE: view = make_paginated_view(base_url, feature_pairs, 0, group_limit, more=True) group['view'] = view grouped.append(group) grouped.sort(key=lambda g: -g['weight']) for group in grouped: del group['weight'] response = ld_node(term) if not grouped and filters is None: return error(response, 404, '%r is not a node in ConceptNet.' % term) else: response['features'] = grouped return success(response)
def lookup_grouped_by_feature(term, filters=None, feature_limit=10): """ Given a query for a concept, return assertions about that concept grouped by their features (for example, "A dog wants to ..." could be a group). """ if not term.startswith('/c/'): return error( {}, 400, 'Only concept nodes (starting with /c/) can be grouped by feature.' ) found = FINDER.lookup_grouped_by_feature(term, limit=(feature_limit + 1)) grouped = [] for groupkey, assertions in found.items(): direction, rel = groupkey base_url = '/query' feature_pairs = groupkey_to_pairs(groupkey, term) url = make_query_url(base_url, feature_pairs) symmetric = direction == 0 group = { '@id': url, 'weight': sum(assertion['weight'] for assertion in assertions), 'feature': dict(feature_pairs), 'edges': assertions[:feature_limit], 'symmetric': symmetric, } if len(assertions) > feature_limit: view = make_paginated_view(base_url, feature_pairs, 0, feature_limit, more=True) group['view'] = view grouped.append(group) grouped.sort(key=lambda g: -g['weight']) for group in grouped: del group['weight'] response = ld_node(term) if not grouped and not filters: return error(response, 404, '%r is not a node in ConceptNet.' % response['label']) else: response['features'] = grouped return success(response)
def lookup_grouped_by_feature(term, filters=None, feature_limit=10): """ Given a query for a concept, return assertions about that concept grouped by their features (for example, "A dog wants to ..." could be a group). """ if not term.startswith('/c/'): return error( {}, 400, 'Only concept nodes (starting with /c/) can be grouped by feature.' ) found = FINDER.lookup_grouped_by_feature(term, limit=(feature_limit + 1)) grouped = [] for groupkey, assertions in found.items(): direction, rel = groupkey base_url = '/query' feature_pairs = groupkey_to_pairs(groupkey, term) url = make_query_url(base_url, feature_pairs) symmetric = direction == 0 group = { '@id': url, 'weight': sum(assertion['weight'] for assertion in assertions), 'feature': dict(feature_pairs), 'edges': assertions[:feature_limit], 'symmetric': symmetric, } if len(assertions) > feature_limit: view = make_paginated_view( base_url, feature_pairs, 0, feature_limit, more=True ) group['view'] = view grouped.append(group) grouped.sort(key=lambda g: -g['weight']) for group in grouped: del group['weight'] response = ld_node(term) if not grouped and not filters: return error( response, 404, '%r is not a node in ConceptNet.' % response['label'] ) else: response['features'] = grouped return success(response)