module Tripod::Finders::ClassMethods
Public Instance Methods
Generate a CONSTRUCT query for the given uri and graph pairs.
# File lib/tripod/finders.rb, line 196 def _construct_query_for_uris_and_graphs(uris_and_graphs) value_pairs = uris_and_graphs.map do |(uri, graph)| u = RDF::URI.new(uri).to_base g = graph ? RDF::URI.new(graph).to_base : 'UNDEF' "(#{u} #{g})" end query = "CONSTRUCT { ?uri ?p ?o . #{ self.all_triples_construct("?uri") }} WHERE { GRAPH ?g { ?uri ?p ?o . #{ self.all_triples_where("?uri") } VALUES (?uri ?g) { #{ value_pairs.join(' ') } } } }" end
Given a select query, perform a DESCRIBE query to get a graph of data from which we create and hydrate a collection of resources.
@option options [ String ] uri_variable The name of the uri variable in the query, if not 'uri' @option options [ String ] graph_variable The name of the uri variable in the query, if not 'graph'
# File lib/tripod/finders.rb, line 161 def _create_and_hydrate_resources_from_sparql(select_sparql, opts={}) # TODO: Optimization?: if return_graph option is false, then don't do this next line? uris_and_graphs = _select_uris_and_graphs(select_sparql, :uri_variable => opts[:uri_variable], :graph_variable => opts[:graph_variable]) #there are no resources if there are no uris and graphs if uris_and_graphs.empty? [] else construct_query = _construct_query_for_uris_and_graphs(uris_and_graphs) graph = _graph_of_triples_from_construct_or_describe(construct_query) _resources_from_graph(graph, uris_and_graphs) end end
For a select query, generate a query which DESCRIBES all the results
@option options [ String ] uri_variable The name of the uri variable in the query, if not 'uri'
# File lib/tripod/finders.rb, line 178 def _describe_query_for_select(select_sparql, opts={}) uri_variable = opts[:uri_variable] || "uri" " CONSTRUCT { ?tripod_construct_s ?tripod_construct_p ?tripod_construct_o . #{ all_triples_construct('?tripod_construct_s') } } WHERE { { SELECT (?#{uri_variable} as ?tripod_construct_s) { #{select_sparql} } } ?tripod_construct_s ?tripod_construct_p ?tripod_construct_o . #{ all_triples_where('?tripod_construct_s') } } " end
given a construct or describe query, return a graph of triples.
# File lib/tripod/finders.rb, line 151 def _graph_of_triples_from_construct_or_describe(construct_query) ntriples_str = Tripod::SparqlClient::Query.query(construct_query, Tripod.ntriples_header_str) _rdf_graph_from_ntriples_string(ntriples_str, graph=nil) end
For a select query, get a raw serialisation of the DESCRIPTION of the resources from the database.
@option options [ String ] uri_variable The name of the uri variable in the query, if not 'uri' @option options [ String ] accept_header The http accept header (default application/n-triples)
# File lib/tripod/finders.rb, line 209 def _raw_describe_select_results(select_sparql, opts={}) accept_header = opts[:accept_header] || Tripod.ntriples_header_str query = _describe_query_for_select(select_sparql, :uri_variable => opts[:uri_variable]) Tripod::SparqlClient::Query.query(query, accept_header) end
given a string of ntriples data, populate an RDF graph. If you pass a graph in, it will add to that one.
# File lib/tripod/finders.rb, line 140 def _rdf_graph_from_ntriples_string(ntriples_string, graph=nil) graph ||= RDF::Graph.new RDF::Reader.for(:ntriples).new(ntriples_string) do |reader| reader.each_statement do |statement| graph << statement end end graph end
given a graph of data, and a hash of uris=>graphs, create and hydrate some resources.
Note: if any of the graphs are not set in the hash, those resources can still be constructed, but not persisted back to DB.
# File lib/tripod/finders.rb, line 218 def _resources_from_graph(graph, uris_and_graphs) repo = add_data_to_repository(graph) resources = [] # TODO: ? if uris_and_graphs not passed in, we could get the # uris from the graph, and just not create the resoruces with a graph # (but they won't be persistable). uris_and_graphs.each do |(u,g)| # instantiate a new resource g ||= {} r = self.new(u, g) # make a graph of data for this resource's uri data_graph = RDF::Graph.new repo.query( [RDF::URI.new(u), :predicate, :object] ) do |statement| data_graph << statement if statement.object.is_a? RDF::Node repo.query( [statement.object, :predicate, :object] ) {|s| data_graph << s} end end # use it to hydrate this resource r.hydrate!(:graph => data_graph) r.new_record = false resources << r end resources end
given a sparql select query, create and hydrate some resources
@option options [ String ] uri_variable The name of the uri variable in the query, if not 'uri' @option options [ String ] graph_variable The name of the uri variable in thh query, if not 'graph'
# File lib/tripod/finders.rb, line 134 def _resources_from_sparql(select_sparql, opts={}) _create_and_hydrate_resources_from_sparql(select_sparql, opts) end
based on the query passed in, build an array of [uri, graph] pairs @param [ String] sparql. The sparql query @param [ Hash ] opts. A hash of options.
@option options [ String ] uri_variable The name of the uri variable in the query, if not 'uri' @option options [ String ] graph_variable The name of the uri variable in thh query, if not 'graph'
# File lib/tripod/finders.rb, line 257 def _select_uris_and_graphs(sparql, opts={}) select_results = Tripod::SparqlClient::Query.select(sparql) uri_variable = opts[:uri_variable] || 'uri' graph_variable = opts[:graph_variable] || 'graph' return [] unless select_results.select{|r| r.keys.length > 0 }.any? select_results.reduce([]) do |memo, result| u = result[uri_variable]['value'] g = result[graph_variable]['value'] if result[graph_variable] memo << [u, g] memo end end
execute a query to return all objects (restricted by this class's rdf_type if specified)
returns a criteria object
# File lib/tripod/finders.rb, line 92 def all Tripod::Criteria.new(self) end
# File lib/tripod/finders.rb, line 96 def count self.all.count end
returns a graph of triples which describe results of the sparql passed in.
@option options [ String ] uri_variable The name of the uri variable in the query, if not 'uri'
# File lib/tripod/finders.rb, line 122 def describe_select_results(select_sparql, opts={}) ntriples_string = _raw_describe_select_results(select_sparql, opts) # this defaults to using n-triples _rdf_graph_from_ntriples_string(ntriples_string) end
returns a graph of triples which describe the uris passed in.
# File lib/tripod/finders.rb, line 105 def describe_uris(uris) graph = RDF::Graph.new if uris.length > 0 uris_sparql_str = uris.map{ |u| "<#{u.to_s}>" }.join(" ") # Do a big describe statement, and read the results into an in-memory repo ntriples_string = Tripod::SparqlClient::Query.query("CONSTRUCT { ?s ?p ?o } WHERE { VALUES ?s { #{uris_sparql_str} }. ?s ?p ?o . }", Tripod.ntriples_header_str) graph = _rdf_graph_from_ntriples_string(ntriples_string, graph) end graph end
Find a Resource
by its uri (and, optionally, by its graph if there are more than one).
@example Find a single resource by a uri.
Person.find('http://ric') Person.find(RDF::URI('http://ric'))
@example Find a single resource by uri and graph
Person.find('http://ric', :graph_uri => 'http://example.com/people')
@example Find a single resource by uri, looking in any graph (i.e. the UNION graph)
Person.find('http://ric', :ignore_graph => true)
@example Find a single resource by uri and graph (DEPRECATED)
Person.find('http://ric', 'http://example.com/people') Person.find(RDF::URI('http://ric'), Person.find(RDF::URI('http://example.com/people')))
@param [ String, RDF::URI ] uri The uri of the resource to find @param [ Hash, String, RDF::URI ] opts Either an options hash (see above), or (for backwards compatibility) the uri of the graph from which to get the resource
@raise [ Tripod::Errors::ResourceNotFound
] If no resource found.
@return [ Resource
] A single resource
# File lib/tripod/finders.rb, line 28 def find(uri, opts={}) if opts.is_a?(String) # backward compatibility hack graph_uri = opts ignore_graph = false else graph_uri = opts.fetch(:graph_uri, nil) ignore_graph = opts.fetch(:ignore_graph, false) end resource = nil if ignore_graph resource = self.new(uri, :ignore_graph => true) else graph_uri ||= self.get_graph_uri unless graph_uri # do a quick select to see what graph to use. select_query = "SELECT * WHERE { GRAPH ?g {<#{uri.to_s}> ?p ?o } } LIMIT 1" result = Tripod::SparqlClient::Query.select(select_query) if result.length > 0 graph_uri = result[0]["g"]["value"] else raise Tripod::Errors::ResourceNotFound.new(uri) end end resource = self.new(uri, :graph_uri => graph_uri.to_s) end resource.hydrate! resource.new_record = false # check that there are triples for the resource (catches case when someone has deleted data # between our original check for the graph and hydrating the object. raise Tripod::Errors::ResourceNotFound.new(uri) if resource.repository.empty? # return the instantiated, hydrated resource resource end
Find a collection of +Resource+s by a SPARQL select statement which returns their uris. Under the hood, this only executes two queries: a select, then a describe.
@example
Person.find_by_sparql('SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri ?p ?o } } LIMIT 3')
@param [ String ] sparql_query. A sparql query which returns a list of uris of the objects. @param [ Hash ] opts. A hash of options.
@option options [ String ] uri_variable The name of the uri variable in thh query, if not 'uri' @option options [ String ] graph_variable The name of the uri variable in thh query, if not 'graph'
@return [ Array ] An array of hydrated resources of this class's type.
# File lib/tripod/finders.rb, line 79 def find_by_sparql(sparql_query, opts={}) _create_and_hydrate_resources_from_sparql(sparql_query, opts) end
# File lib/tripod/finders.rb, line 100 def first self.all.first end
execute a where clause on this resource.
returns a criteria object
# File lib/tripod/finders.rb, line 85 def where(sparql_snippet) criteria = Tripod::Criteria.new(self) criteria.where(sparql_snippet) end