Class: RDF::Query::Solutions

Inherits:
Array
  • Object
show all
Defined in:
lib/rdf/query/solutions.rb

Overview

An RDF basic graph pattern (BGP) query solution sequence.

Examples:

Filtering solutions using a hash

solutions.filter(author:  RDF::URI("http://ar.to/#self"))
solutions.filter(author:  "Gregg Kellogg")
solutions.filter(author:  [RDF::URI("http://ar.to/#self"), "Gregg Kellogg"])
solutions.filter(updated: RDF::Literal(Date.today))

Filtering solutions using a block

solutions.filter { |solution| solution.author.literal? }
solutions.filter { |solution| solution.title.to_s =~ /^SPARQL/ }
solutions.filter { |solution| solution.price < 30.5 }
solutions.filter { |solution| solution.bound?(:date) }
solutions.filter { |solution| solution.age.datatype == RDF::XSD.integer }
solutions.filter { |solution| solution.name.language == :es }

Reordering solutions based on a variable or proc

solutions.order_by(:updated)
solutions.order_by(:updated, :created)
solutions.order_by(:updated, lambda {|a, b| b <=> a})

Selecting/Projecting particular variables only

solutions.select(:title)
solutions.select(:title, :description)
solutions.project(:title)

Eliminating duplicate solutions

solutions.distinct

Limiting the number of solutions

solutions.offset(20).limit(10)

Counting the number of matching solutions

solutions.count
solutions.count { |solution| solution.price < 30.5 }

Iterating over all found solutions

solutions.each { |solution| puts solution.inspect }

Since:

  • 0.3.0

Instance Method Summary collapse

Instance Method Details

#bindingsHash{Symbol => Array<RDF::Term>}

Returns hash of bindings from each solution. Each bound variable will have an array of bound values representing those from each solution, where a given solution will have just a single value for each bound variable

Returns:

Since:

  • 0.3.0



97
98
99
100
101
102
103
104
105
106
# File 'lib/rdf/query/solutions.rb', line 97

def bindings
  bindings = {}
  each do |solution|
    solution.each do |key, value|
      bindings[key] ||= []
      bindings[key] << value
    end
  end
  bindings
end

#countInteger #count({ |solution| ... }) {|solution| ... } ⇒ Integer

Returns the number of matching query solutions.

Overloads:

  • #countInteger

    Returns:

    • (Integer)
  • #count({ |solution| ... }) {|solution| ... } ⇒ Integer

    Yields:

    • (solution)

    Yield Parameters:

    Yield Returns:

    • (Boolean)

    Returns:

    • (Integer)

Returns:

  • (Integer)

Since:

  • 0.3.0



59
60
61
# File 'lib/rdf/query/solutions.rb', line 59

def count(&block)
  super
end

#distinctself Also known as: distinct!, reduced, reduced!

Ensures that the solutions in this solution sequence are unique.

Returns:

  • (self)

Since:

  • 0.3.0



212
213
214
215
# File 'lib/rdf/query/solutions.rb', line 212

def distinct
  self.uniq!
  self
end

#filter(criteria = {}) {|solution| ... } ⇒ self Also known as: filter!

Filters this solution sequence by the given criteria.

Parameters:

  • criteria (Hash{Symbol => Object}) (defaults to: {})

Yields:

  • (solution)

Yield Parameters:

Yield Returns:

  • (Boolean)

Returns:

  • (self)

Since:

  • 0.3.0



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/rdf/query/solutions.rb', line 116

def filter(criteria = {})
  if block_given?
    self.reject! do |solution|
      !yield(solution.is_a?(Solution) ? solution : Solution.new(solution))
    end
  else
    self.reject! do |solution|
      solution = solution.is_a?(Solution) ? solution : Solution.new(solution)
      results = criteria.map do |name, value|
        case value
        when Array then value.any? {|v| solution[name] == v}
        when Regexp then solution[name].to_s.match(value)
        else solution[name] == value
        end
      end
      !results.all?
    end
  end
  self
end

#have_variables?(variables) ⇒ Boolean Also known as: has_variables?

Returns true if this solution sequence contains bindings for any of the given variables.

Parameters:

  • variables (Array<Symbol, #to_sym>)

    an array of variables to check

Returns:

  • (Boolean)

    true or false

See Also:

Since:

  • 0.3.0



87
88
89
# File 'lib/rdf/query/solutions.rb', line 87

def have_variables?(variables)
  self.any? { |solution| solution.has_variables?(variables) }
end

#limit(length) ⇒ self Also known as: limit!

Limits the number of solutions in this solution sequence to a maximum of length.

Parameters:

  • length (Integer, #to_i)

    zero or a positive integer

Returns:

  • (self)

Raises:

  • (ArgumentError)

    if length is negative

Since:

  • 0.3.0



244
245
246
247
248
249
250
251
252
# File 'lib/rdf/query/solutions.rb', line 244

def limit(length)
  length = length.to_i
  raise ArgumentError, "expected zero or a positive integer, got #{length}" if length < 0
  case length
    when 0 then self.clear
    else self.slice!(length..-1) if length < self.size
  end
  self
end

#minus(other) ⇒ RDF::Query::Solutions

Difference between solution sets, from SPARQL 1.1.

The minus operation on solutions returns those solutions which either have no compatible solution in other, or the solution domains are disjoint.

Parameters:

Returns:

See Also:

Since:

  • 0.3.0



146
147
148
149
150
# File 'lib/rdf/query/solutions.rb', line 146

def minus(other)
  self.dup.filter! do |soln|
    !other.any? {|soln2| soln.compatible?(soln2) && !soln.disjoint?(soln2)}
  end
end

#offset(start) ⇒ self Also known as: offset!

Limits this solution sequence to bindings starting from the start offset in the overall solution sequence.

Parameters:

  • start (Integer, #to_i)

    zero or a positive or negative integer

Returns:

  • (self)

Since:

  • 0.3.0



227
228
229
230
231
232
233
# File 'lib/rdf/query/solutions.rb', line 227

def offset(start)
  case start = start.to_i
    when 0 then nil
    else self.slice!(0...start)
  end
  self
end

#order(*variables) {|solution| ... } ⇒ self Also known as: order_by

Reorders this solution sequence by the given variables.

Variables may be symbols or Variable instances. A variable may also be a Procedure/Lambda, compatible with ::Enumerable#sort. This takes two arguments (solutions) and returns -1, 0, or 1 equivalently to <=>.

If called with a block, variables are ignored, and the block is invoked with pairs of solutions. The block is expected to return -1, 0, or 1 equivalently to <=>.

Parameters:

Yields:

  • (solution)

Yield Parameters:

Yield Returns:

  • (Integer)

    -1, 0, or 1 depending on value of comparator

Returns:

  • (self)

Since:

  • 0.3.0



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/rdf/query/solutions.rb', line 168

def order(*variables)
  if variables.empty? && !block_given?
    raise ArgumentError, "wrong number of arguments (0 for 1)"
  else
    self.sort! do |a, b|
      if block_given?
        yield((a.is_a?(Solution) ? a : Solution.new(a)), (b.is_a?(Solution) ? b : Solution.new(b)))
      else
        # Try each variable until a difference is found.
        variables.inject(nil) do |memo, v|
          memo || begin
            comp = v.is_a?(Proc) ? v.call(a, b) : (v = v.to_sym; a[v] <=> b[v])
            comp == 0 ? false : comp
          end
        end || 0
      end
    end
  end
  self
end

#project(*variables) ⇒ self Also known as: select

Restricts this solution sequence to the given variables only.

Parameters:

  • variables (Array<Symbol, #to_sym>)

Returns:

  • (self)

Since:

  • 0.3.0



195
196
197
198
199
200
201
202
203
204
205
# File 'lib/rdf/query/solutions.rb', line 195

def project(*variables)
  if variables.empty?
    raise ArgumentError, "wrong number of arguments (0 for 1)"
  else
    variables.map!(&:to_sym)
    self.each do |solution|
      solution.bindings.delete_if { |k, v| !variables.include?(k.to_sym) }
    end
  end
  self
end

#variable_namesArray<Symbol>

Returns an array of the distinct variable names used in this solution sequence.

Returns:

  • (Array<Symbol>)

Since:

  • 0.3.0



68
69
70
71
72
73
74
75
76
# File 'lib/rdf/query/solutions.rb', line 68

def variable_names
  variables = self.inject({}) do |result, solution|
    solution.each_name do |name|
      result[name] ||= true
    end
    result
  end
  variables.keys
end