Class: Moped::Query

Inherits:
Object show all
Includes:
Enumerable
Defined in:
lib/moped/query.rb

Overview

The Query class encapsulates all of the logic related to building selectors for querying, updating, or removing documents in a collection.

Examples:

people = db[:people]
people.find.entries # => [{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}]
people.find.skip(2).first # => { id: 3 }
people.find.skip(2).update(name: "John")
people.find.skip(2).first # => { id: 3, name: "John" }

people.find(name: nil).update_all(name: "Unknown")
people.find.one # => { id: 5, name: "Unknown" }
people.find.first # => { id: 5, name: "Unknown" }
people.find.select(name: 0).first # => { id: 5 }
people.find(name: "Unknown").remove_all
people.find.count # => 1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(collection, selector) ⇒ Query

Initialize the query.

Examples:

Initialize the query.

Query.new(collection, selector)

Parameters:

  • collection (Collection)

    The query’s collection.

  • selector (Hash)

    The query’s selector.

Since:

  • 1.0.0



169
170
171
172
173
174
175
176
# File 'lib/moped/query.rb', line 169

def initialize(collection, selector)
  @collection, @selector = collection, selector
  @operation = Protocol::Query.new(
    collection.database.name,
    collection.name,
    selector
  )
end

Instance Attribute Details

#collectionObject (readonly)

Returns the value of attribute collection.



25
26
27
# File 'lib/moped/query.rb', line 25

def collection
  @collection
end

#collection The collection to execute the query on.(Thecollectiontoexecutethequeryon.) ⇒ Object (readonly)



25
# File 'lib/moped/query.rb', line 25

attr_reader :collection, :operation, :selector

#operationObject (readonly)

Returns the value of attribute operation.



25
26
27
# File 'lib/moped/query.rb', line 25

def operation
  @operation
end

#operation The query operation.(Thequeryoperation.) ⇒ Object (readonly)



25
# File 'lib/moped/query.rb', line 25

attr_reader :collection, :operation, :selector

#selectorObject (readonly)

Returns the value of attribute selector.



25
26
27
# File 'lib/moped/query.rb', line 25

def selector
  @selector
end

#selector The query selector.(Thequeryselector.) ⇒ Object (readonly)



25
# File 'lib/moped/query.rb', line 25

attr_reader :collection, :operation, :selector

Instance Method Details

#batch_size(batch_size) ⇒ Query

Set the query’s batch size.

Examples:

Set the batch size.

db[:people].find.batch_size(20)

Parameters:

  • limit (Integer)

    The number of documents per batch.

Returns:

Since:

  • 1.0.0



203
204
205
206
# File 'lib/moped/query.rb', line 203

def batch_size(batch_size)
  operation.batch_size = batch_size
  self
end

#count(limit = false) ⇒ Integer

Get the count of matching documents in the query.

Examples:

Get the count.

db[:people].find.count

Returns:

  • (Integer)

    The number of documents that match the selector.

Since:

  • 1.0.0



35
36
37
38
39
40
# File 'lib/moped/query.rb', line 35

def count(limit = false)
  command = { count: collection.name, query: selector }
  command.merge!(skip: operation.skip, limit: operation.limit) if limit
  result = collection.database.command(command)
  result["n"].to_i
end

#distinct(key) ⇒ Array<Object ] The distinct values.

Get the distinct values in the collection for the provided key.

Examples:

Get the distinct values.

db[:people].find.distinct(:name)

Parameters:

Returns:

Since:

  • 1.0.0



52
53
54
55
56
57
58
59
# File 'lib/moped/query.rb', line 52

def distinct(key)
  result = collection.database.command(
    distinct: collection.name,
    key: key.to_s,
    query: selector
  )
  result["values"]
end

#each {|document| ... } ⇒ Enumerator Also known as: cursor

Iterate through documents matching the query’s selector.

Examples:

Iterate over the matching documents.

db[:people].find.each do |doc|
  #...
end

Yield Parameters:

  • document (Hash)

    each matching document

Returns:

  • (Enumerator)

    The enumerator.

Since:

  • 1.0.0



73
74
75
76
77
78
79
80
# File 'lib/moped/query.rb', line 73

def each
  cursor = Cursor.new(session, operation)
  enum = cursor.to_enum
  enum.each do |document|
    yield document
  end if block_given?
  enum
end

#explainHash

Explain the current query.

Examples:

Explain the query.

db[:people].find.explain

Returns:

  • (Hash)

    The explain document.

Since:

  • 1.0.0



91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/moped/query.rb', line 91

def explain
  explanation = operation.selector.dup
  hint = explanation["$hint"]
  sort = explanation["$orderby"]
  max_scan = explanation["$maxScan"]
  explanation = {
    "$query" => selector,
    "$explain" => true,
  }
  explanation["$orderby"] = sort if sort
  explanation["$hint"] = hint if hint
  explanation["$maxScan"] = max_scan if max_scan
  Query.new(collection, explanation).limit(-(operation.limit.abs)).each { |doc| return doc }
end

#firstHash Also known as: one

Get the first matching document.

Examples:

Get the first matching document.

db[:people].find.first

Returns:

  • (Hash)

    The first document that matches the selector.

Since:

  • 1.0.0



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/moped/query.rb', line 114

def first
  reply = session.context.query(
    operation.database,
    operation.collection,
    operation.selector,
    fields: operation.fields,
    flags: operation.flags,
    skip: operation.skip,
    limit: -1
  )
  reply.documents.first
end

#hint(hint) ⇒ Query

Apply an index hint to the query.

Examples:

Apply an index hint.

db[:people].find.hint("$natural" => 1)

Parameters:

  • hint (Hash)

    The index hint.

Returns:

Since:

  • 1.0.0



138
139
140
141
142
# File 'lib/moped/query.rb', line 138

def hint(hint)
  upgrade_to_advanced_selector
  operation.selector["$hint"] = hint
  self
end

#limit(limit) ⇒ Query

Set the query’s limit.

Examples:

Set the limit.

db[:people].find.limit(20)

Parameters:

  • limit (Integer)

    The number of documents to limit.

Returns:

Since:

  • 1.0.0



188
189
190
191
# File 'lib/moped/query.rb', line 188

def limit(limit)
  operation.limit = limit
  self
end

#max_scan(max) ⇒ Query

Apply a max scan limit to the query.

Examples:

Limit the query to only scan up to 100 documents

db[:people].find.max_scan(100)

Parameters:

  • max (Integer)

    The maximum number of documents to scan

Returns:

Since:

  • 1.4.0



154
155
156
157
158
# File 'lib/moped/query.rb', line 154

def max_scan(max)
  upgrade_to_advanced_selector
  operation.selector["$maxScan"] = max
  self
end

#modify(change, options = {}) ⇒ Hash

Execute a $findAndModify on the query.

Examples:

Find and modify a document, returning the original.

db[:bands].find.modify({ "$inc" => { likes: 1 }})

Find and modify a document, returning the updated document.

db[:bands].find.modify({ "$inc" => { likes: 1 }}, new: true)

Find and return a document, removing it from the database.

db[:bands].find.modify({}, remove: true)

Find and return a document, upserting if no match found.

db[:bands].find.modify({}, upsert: true, new: true)

Parameters:

  • change (Hash)

    The changes to make to the document.

  • options (Hash) (defaults to: {})

    The options.

Options Hash (options):

  • :new (Object)

    Set to true if you want to return the updated document.

  • :remove (Object)

    Set to true if the document should be deleted.

  • :upsert (Object)

    Set to true if you want to upsert

Returns:

  • (Hash)

    The document.

Since:

  • 1.0.0



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/moped/query.rb', line 245

def modify(change, options = {})
  command = {
    findAndModify: collection.name,
    query: selector
  }.merge(options)

  command[:sort] = operation.selector["$orderby"] if operation.selector["$orderby"]
  command[:fields] = operation.fields if operation.fields
  command[:update] = change unless options[:remove]

  result = session.with(consistency: :strong) do |sess|
    sess.command(command)["value"]
  end

  # Keeping moped compatibility with mongodb >= 2.2.0-rc0
  options[:upsert] && !result ? {} : result
end

#no_timeoutQuery

Disable cursor timeout

Examples:

Disable cursor timeout.

db[:people].find.no_timeout

Returns:

Since:

  • 1.0.0



216
217
218
219
# File 'lib/moped/query.rb', line 216

def no_timeout
  operation.no_timeout = true
  self
end

#removeHash?

Remove a single document matching the query’s selector.

Examples:

Remove a single document.

db[:people].find(name: "John").remove

Returns:

  • (Hash, nil)

    If in safe mode the last error result.

Since:

  • 1.0.0



271
272
273
274
275
276
277
278
279
280
# File 'lib/moped/query.rb', line 271

def remove
  session.with(consistency: :strong) do |session|
    session.context.remove(
      operation.database,
      operation.collection,
      operation.basic_selector,
      flags: [ :remove_first ]
    )
  end
end

#remove_allHash?

Remove multiple documents matching the query’s selector.

Examples:

Remove all matching documents.

db[:people].find(name: "John").remove_all

Returns:

  • (Hash, nil)

    If in safe mode the last error result.

Since:

  • 1.0.0



290
291
292
293
294
295
296
297
298
# File 'lib/moped/query.rb', line 290

def remove_all
  session.with(consistency: :strong) do |session|
    session.context.remove(
      operation.database,
      operation.collection,
      operation.basic_selector
    )
  end
end

#select(select) ⇒ Query

Set the fields to include or exclude from the query.

Examples:

Select the fields to include or exclude.

db[:people].find.select(name: 1).one # => { name: "John" }

Parameters:

  • select (Hash)

    The inclusions or exclusions.

Returns:

Since:

  • 1.0.0



310
311
312
313
# File 'lib/moped/query.rb', line 310

def select(select)
  operation.fields = select
  self
end

#skip(skip) ⇒ Query

Set the number of documents to skip.

Examples:

Set the number to skip.

db[:people].find.skip(20)

Parameters:

  • skip (Integer)

    The number of documents to skip.

Returns:

Since:

  • 1.0.0



325
326
327
328
# File 'lib/moped/query.rb', line 325

def skip(skip)
  operation.skip = skip
  self
end

#sort(sort) ⇒ Query

Set the sort order for the query.

Examples:

Set the sort order.

db[:people].find.sort(name: 1, age: -1).one

Parameters:

  • sort (Hash)

    The order as key/(1/-1) pairs.

Returns:

Since:

  • 1.0.0



340
341
342
343
344
# File 'lib/moped/query.rb', line 340

def sort(sort)
  upgrade_to_advanced_selector
  operation.selector["$orderby"] = sort
  self
end

#tailableQuery

Tell the query to create a tailable cursor.

Examples:

Tell the query the cursor is tailable.

db[:people].find.tailable

Returns:

Since:

  • 1.3.0



354
355
356
357
# File 'lib/moped/query.rb', line 354

def tailable
  operation.flags.push(:tailable, :await_data)
  self
end

#update(change, flags = nil) ⇒ Hash?

Update a single document matching the query’s selector.

Examples:

Update the first matching document.

db[:people].find(_id: 1).update(name: "John")

Parameters:

  • change (Hash)

    The changes to make to the document

  • flags (Array) (defaults to: nil)

    An array of operation flags. Valid values are: :multi and :upsert

Returns:

  • (Hash, nil)

    If in safe mode the last error result.

Since:

  • 1.0.0



371
372
373
374
375
376
377
378
379
380
381
# File 'lib/moped/query.rb', line 371

def update(change, flags = nil)
  session.with(consistency: :strong) do |session|
    session.context.update(
      operation.database,
      operation.collection,
      operation.selector["$query"] || operation.selector,
      change,
      flags: flags
    )
  end
end

#update_all(change) ⇒ Hash?

Update multiple documents matching the query’s selector.

Examples:

Update multiple documents.

db[:people].find(name: "John").update_all(name: "Mary")

Parameters:

  • change (Hash)

    The changes to make to the documents

Returns:

  • (Hash, nil)

    If in safe mode the last error result.

Since:

  • 1.0.0



393
394
395
# File 'lib/moped/query.rb', line 393

def update_all(change)
  update(change, [ :multi ])
end

#upsert(change) ⇒ Hash?

Update an existing document with change, otherwise create one.

Examples:

Upsert the changes.

db[:people].find.entries # => { name: "John" }
db[:people].find(name: "John").upsert(name: "James")
db[:people].find.entries # => { name: "James" }
db[:people].find(name: "John").upsert(name: "Mary")
db[:people].find.entries # => [{ name: "James" }, { name: "Mary" }]

Parameters:

  • change (Hash)

    The changes to make to the the document.

Returns:

  • (Hash, nil)

    If in safe mode the last error result.

Since:

  • 1.0.0



411
412
413
# File 'lib/moped/query.rb', line 411

def upsert(change)
  update(change, [ :upsert ])
end