Class: Lotus::Model::Adapters::Rethinkdb::Query

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable, RethinkDB::Shortcuts
Defined in:
lib/lotus/model/adapters/rethinkdb/query.rb

Overview

Query the database with a powerful API.

All the methods are chainable, it allows advanced composition of ReQL conditions.

This works as a lazy filtering mechanism: the documents are fetched from the database only when needed.

It implements Ruby’s ‘Enumerable` and borrows some methods from `Array`. Expect a query to act like them.

Examples:


query.where(language: 'ruby')
     .and(framework: 'lotus')
     .desc(:users_count).all

# the documents are fetched only when we invoke #all

Since:

  • 0.1.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(collection, context = nil, &blk) ⇒ Lotus::Model::Adapters::Rethinkdb::Query

Initialize a query

Parameters:

Since:

  • 0.1.0



52
53
54
55
56
57
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 52

def initialize(collection, context = nil, &blk)
  @collection, @context = collection, context
  @conditions = []

  instance_eval(&blk) if block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &blk) ⇒ Object (protected)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Handles missing methods for query combinations

See Also:

  • Lotus::Model::Adapters:Rethinkdb::Query#apply

Since:

  • 0.1.0



388
389
390
391
392
393
394
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 388

def method_missing(m, *args, &blk)
  if @context.respond_to?(m)
    apply @context.public_send(m, *args, &blk)
  else
    super
  end
end

Instance Attribute Details

#conditionsObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 0.1.0



41
42
43
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 41

def conditions
  @conditions
end

Instance Method Details

#allArray

Resolves the query by fetching documents from the database and translating them into entities.

Returns:

  • (Array)

    a collection of entities

Since:

  • 0.1.0



65
66
67
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 65

def all
  scoped.execute
end

#average(field) ⇒ Numeric Also known as: avg

Returns the average of the values for the given field.

Examples:


query.average(:comments_count)

# => r.avg(:comments_count)

Parameters:

  • field (Symbol)

    the column name

Returns:

  • (Numeric)

Since:

  • 0.1.0



295
296
297
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 295

def average(field)
  scoped.avg(field)
end

#countFixnum

Returns a count of the records for the current conditions.

Examples:


query.where(author_id: 23).count # => 5

Returns:

  • (Fixnum)

Since:

  • 0.1.0



358
359
360
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 358

def count
  scoped.count
end

#desc(*fields) ⇒ Object

Specify the descending order of the documents, sorted by the given fields or index. Identify an index using ‘{ index: :key }`.

The last invokation of this method takes precidence. Previously called sorts will be overwritten by RethinkDB.

Examples:

Single field


query.desc(:name)

# => r.order_by(r.desc(:name))

Multiple columns


query.desc(:name, :year)

# => r.order_by(r.desc(:name), r.desc(:year))

Single index


query.desc(index: :date)

# => r.order_by(index: r.desc(:date))

Mixed fields and index


query.desc(:name, :year, { index: r.desc(:date) })

# => r.order_by(r.desc(:name), r.desc(:year), { index:
                r.desc(:date) })

Returns:

  • self

See Also:

Since:

  • 0.1.0



260
261
262
263
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 260

def desc(*fields)
  conditions.push([:order_by, *_desc_wrapper(*fields)])
  self
end

#has_fields(*fields) ⇒ Object

Only include documents with the given fields.

Examples:

Single column


query.has_fields(:name)

# => r.has_fields(:name)

Multiple columns


query.has_fields(:name, :year)

# => r.has_fields(:name, :year)

Parameters:

  • fields (Array<Symbol>)

Returns:

  • self

Since:

  • 0.1.0



154
155
156
157
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 154

def has_fields(*fields) # rubocop:disable Style/PredicateName
  conditions.push([:has_fields, *fields])
  self
end

#limit(number) ⇒ Object

Limit the number of documents to return.

This operation is performed at the database level with r.limit().

Examples:


query.limit(1)

# => r.limit(1)

Parameters:

  • number (Fixnum)

Returns:

  • self

Since:

  • 0.1.0



174
175
176
177
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 174

def limit(number)
  conditions.push([:limit, number])
  self
end

#max(field) ⇒ Object

Returns the maximum value for the given field.

Examples:

With numeric type


query.max(:comments_count)

# r.max(:comments_count)

With string type


query.max(:title)

# => r.max(:title)

Parameters:

  • field (Symbol)

    the field name

Returns:

  • result

Since:

  • 0.1.0



320
321
322
323
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 320

def max(field)
  has_fields(field)
  scoped.max(field)
end

#min(field) ⇒ Object

Returns the minimum value for the given field.

Examples:

With numeric type


query.min(:comments_count)

# => r.min(:comments_count)

With string type


query.min(:title)

# => r.min(:title)

Parameters:

  • field (Symbol)

    the field name

Returns:

  • result

Since:

  • 0.1.0



344
345
346
347
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 344

def min(field)
  has_fields(field)
  scoped.min(field)
end

#order(*fields) ⇒ Object Also known as: asc

Specify the ascending order of the documents, sorted by the given fields or index. Identify an index using ‘{ index: :key }`.

The last invokation of this method takes precidence. Previously called sorts will be overwritten by RethinkDB.

Examples:

Single field


query.order(:name)

# => r.order_by(:name)

Multiple columns


query.order(:name, :year)

# => r.order_by(:name, :year)

Single index


query.order(index: :date)

# => r.order_by(index: :date)

Mixed fields and index


query.order(:name, :year, index: :date)

# => r.order_by(:name, :year, index: :date)

Parameters:

  • fields (Array<Symbol, Hash>)

    the field names, optionally with an index identifier

Returns:

  • self

See Also:

Since:

  • 0.1.0



217
218
219
220
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 217

def order(*fields)
  conditions.push([:order_by, *fields])
  self
end

#pluck(*fields) ⇒ Object

Pluck only the specified fields. Documents without the fields are omitted.

By default a query includes all the fields of a table.

Examples:

Single field


query.pluck(:name)

# => r.pluck(:name)

Multiple fields


query.pluck(:name, :year)

# => r.pluck(:name, :year)

Parameters:

  • fields (Array<Symbol>)

Returns:

  • self

Since:

  • 0.1.0



130
131
132
133
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 130

def pluck(*fields)
  conditions.push([:pluck, *fields])
  self
end

#scopedLotus::Model::Adapters::Rethinkdb::Collection

Apply all the conditions and returns a filtered collection.

This operation is idempotent, and the returned result didn’t fetched the documents yet.



370
371
372
373
374
375
376
377
378
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 370

def scoped
  scope = @collection

  conditions.each do |(method, *args)|
    scope = scope.public_send(method, *args)
  end

  scope
end

#sum(field) ⇒ Numeric

Returns the sum of the values for the given field.

Examples:


query.sum(:comments_count)

# => r.sum(:comments_count)

Parameters:

  • field (Symbol)

    the field name

Returns:

  • (Numeric)

Since:

  • 0.1.0



278
279
280
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 278

def sum(field)
  scoped.sum(field)
end

#where(condition = nil, &blk) ⇒ Object Also known as: and

Adds a condition like SQL ‘WHERE` using r.filter().

It accepts a ‘Hash` with only one pair. The key must be the name of the field expressed as a `Symbol`. The value is the one used by the ReQL query

Examples:

Fixed value


query.where(language: 'ruby')

# => r.filter(language: 'ruby')

Multiple conditions


query.where(language: 'ruby')
     .where(framework: 'lotus')

# => r.filter(language: 'ruby').filter('framework: 'lotus')

Blocks


query.where { |doc| doc['age'] > 10 }

# => r.filter { |doc| doc.bracket('age').gt('10') }

Parameters:

  • condition (Hash) (defaults to: nil)

Returns:

  • self

Since:

  • 0.1.0



99
100
101
102
103
104
# File 'lib/lotus/model/adapters/rethinkdb/query.rb', line 99

def where(condition = nil, &blk)
  condition = condition || blk ||
              fail(ArgumentError, 'You need to specify a condition.')
  conditions.push([:filter, condition])
  self
end