def query_S(s, direct, contexts): """ Construct :class:`surf.query.Query` with `?p`, `?v` and `?g`, `?c` as unknowns. """ s, v = direct and (s, '?v') or ('?v', s) query = select('?p', '?v', '?c', '?g').distinct() # Get predicate, objects and optionally rdf:type & named graph of # subject rdf:type and object rdf:type # TODO fails under Virtuoso as V. doesn't allow ?g to be bound to two # optional matches query.where((s, '?p', v)).optional_group(('?v', a, '?c'))\ .optional_group(named_group('?g', (s, a, v)))\ .optional_group(named_group('?g', ('?v', a, '?c'))) if contexts: query.from_(*contexts) query.from_named(*contexts) return query
def query_Ask(subject, context): """ Construct :class:`surf.query.Query` of type **ASK**. """ query = ask() if context: pattern = named_group(context, (subject, '?p', '?o')) query.where(pattern) else: query.where((subject, '?p', '?o')) return query
def query_SP(s, p, direct, contexts): """ Construct :class:`surf.query.Query` with `?v` and `?g`, `?c` as unknowns. """ s, v = direct and (s, '?v') or ('?v', s) query = select('?v', '?c', '?g').distinct() query.where((s, p, v)).optional_group(('?v', a, '?c'))\ .optional_group(named_group('?g', ('?v', a, '?c'))) if contexts: query.from_(*contexts) query.from_named(*contexts) return query
def query_ask(s, context): """ Construct :class:`surf.query.Query` of type **ASK**. :param s: the `subject` :param context: the context :return: the query :rtype: :class:`surf.query.Query` """ query = ask() if context: pattern = named_group(context, (s, '?p', '?o')) query.where(pattern) else: query.where((s, '?p', '?o')) return query
def query_P_S(c, p, direct, context): """ Construct :class:`surf.query.Query` with `?s` and `?g`, `?c` as unknowns. """ query = select('?s', '?c', '?g').distinct() if context: query.from_(context) query.from_named(context) for i in range(len(p)): s, v = direct and ('?s', '?v%d' % i) or ('?v%d' % i, '?s') if type(p[i]) is URIRef: query.where((s, p[i], v)) query.optional_group(('?s', a, '?c')) query.optional_group(named_group('?g', ('?s', a, '?c'))) return query
def _get_by(self, params): # Decide which loading strategy to use if "full" in params: if self.use_subqueries: return self.__get_by_subquery(params) else: return self.__get_by_n_queries(params) # No details, just subjects and classes query = select("?s", "?c", "?g") self.__apply_limit_offset_order_get_by_filter(params, query) query.optional_group(("?s", a, "?c")) # Query for the same tuple to get the named graph if obtainable query.optional_group(named_group("?g", ("?s", a, "?c"))) contexts = params.get("contexts", None) if contexts: query.from_(*contexts) query.from_named(*contexts) # Load just subjects and their types table = self._to_table(self._execute(query)) # Create response structure, preserve order, don't include # duplicate subjects if some subject has multiple types subjects = {} results = [] for match in table: subject = match["s"] if not subject in subjects: instance_data = {"direct" : {a : {}}} subjects[subject] = instance_data results.append((subject, instance_data)) # "context" comes from an optional group and is missing if the # triple is stored in the unamed graph context = match.get("g") if "c" in match: concept = match["c"] subjects[subject]["direct"][a][concept] = {context: []} return results
def __get_by_subquery(self, params): contexts = params.get("contexts", None) inner_query = select("?s") inner_params = params.copy() if "order" in params: # "order" needs to stay in subquery, # but doesn't do anything useful in main query del params["order"] self.__apply_limit_offset_order_get_by_filter(inner_params, inner_query) query = select("?s", "?p", "?v", "?c", "?g").distinct() # Get values with object type & context # TODO we need to query both contexts, from ?s -> rdf_type & ?v -> rdf_type but Virtuoso does not bind ?g twice. Bug or feature? query.group(('?s', '?p', '?v'), optional_group(('?v', a, '?c')), optional_group(named_group("?g", ("?s", a, "?v")))) #optional_group(named_group("?g", ("?v", a, "?c")))) query.where(inner_query) if contexts: query.from_(*contexts) query.from_named(*contexts) # Need ordering in outer query if "order" in params: if params["order"] == True: # Order by subject URI query.order_by("?s") else: # Match another variable, order by it query.optional_group(("?s", params["order"], "?order")) query.order_by("?order") table = self._to_table(self._execute(query)) subjects = {} results = [] for match in table: # Make sure subject and predicate are URIs (they have to be!), # this works around bug in Virtuoso -- it sometimes returns # URIs as Literals. subject = URIRef(match["s"]) predicate = URIRef(match["p"]) value = match["v"] # Add subject to result list if it's not there if not subject in subjects: instance_data = {"direct" : {}} subjects[subject] = instance_data results.append((subject, instance_data)) # Add predicate to subject's direct predicates if it's not there direct_attributes = subjects[subject]["direct"] if not predicate in direct_attributes: direct_attributes[predicate] = {} # "context" comes from an optional group and is missing if the # triple is stored in the unamed graph context = match.get("g") # Add value to subject->predicate if ... predicate_values = direct_attributes[predicate] if not value in predicate_values: predicate_values[value] = {context: []} # Add RDF type of the value to subject->predicate->value list if "c" in match: predicate_values[value][context].append(match["c"]) return results