Class: Mongocore::Query

Inherits:
Object
  • Object
show all
Defined in:
lib/mongocore/query.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(m, q = {}, o = {}) ⇒ Query

Mongocore query initializer



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/mongocore/query.rb', line 16

def initialize(m, q = {}, o = {})

  # Storing model class. The instance can be found in options[:source]
  @model = m

  # The model name is singular, the collection name is plural
  @colname = m.to_s.downcase.pluralize.to_sym

  # Storing the Mongo::Collection object
  @collection = Mongocore.db[@colname]

  # Default options
  o[:source] ||= nil
  o[:chain] ||= []
  o[:skip] ||= 0
  o[:limit] ||= 0
  o[:sort] ||= Mongocore.sort.dup
  o[:projection] ||= {}

  # Storing query and options
  @query, @options = @model.schema.ids(hashify(q)), o

  # Set up cache
  @cache = Mongocore::Cache.new(self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *arguments, &block) ⇒ Object

Call and return the scope if it exists



207
208
209
210
211
212
213
# File 'lib/mongocore/query.rb', line 207

def method_missing(name, *arguments, &block)
  if @model.schema.scopes.has_key?(name)
    @options[:chain] << name
    return @model.send(name, @query, @options)
  end
  super
end

Instance Attribute Details

#cacheObject

# # # # # # # The Query class keeps the cursor and handles the connection with the underlying MongoDB database. A new query is created every time you call find, sort, limit, count, update, scopes and associations.

Every query can be chained, but only one find is ever done to the database, it’s only the parameters that change.



13
14
15
# File 'lib/mongocore/query.rb', line 13

def cache
  @cache
end

#collectionObject

# # # # # # # The Query class keeps the cursor and handles the connection with the underlying MongoDB database. A new query is created every time you call find, sort, limit, count, update, scopes and associations.

Every query can be chained, but only one find is ever done to the database, it’s only the parameters that change.



13
14
15
# File 'lib/mongocore/query.rb', line 13

def collection
  @collection
end

#colnameObject

# # # # # # # The Query class keeps the cursor and handles the connection with the underlying MongoDB database. A new query is created every time you call find, sort, limit, count, update, scopes and associations.

Every query can be chained, but only one find is ever done to the database, it’s only the parameters that change.



13
14
15
# File 'lib/mongocore/query.rb', line 13

def colname
  @colname
end

#modelObject

# # # # # # # The Query class keeps the cursor and handles the connection with the underlying MongoDB database. A new query is created every time you call find, sort, limit, count, update, scopes and associations.

Every query can be chained, but only one find is ever done to the database, it’s only the parameters that change.



13
14
15
# File 'lib/mongocore/query.rb', line 13

def model
  @model
end

#optionsObject

# # # # # # # The Query class keeps the cursor and handles the connection with the underlying MongoDB database. A new query is created every time you call find, sort, limit, count, update, scopes and associations.

Every query can be chained, but only one find is ever done to the database, it’s only the parameters that change.



13
14
15
# File 'lib/mongocore/query.rb', line 13

def options
  @options
end

#queryObject

# # # # # # # The Query class keeps the cursor and handles the connection with the underlying MongoDB database. A new query is created every time you call find, sort, limit, count, update, scopes and associations.

Every query can be chained, but only one find is ever done to the database, it’s only the parameters that change.



13
14
15
# File 'lib/mongocore/query.rb', line 13

def query
  @query
end

Instance Method Details

#allObject

Return all documents



111
112
113
# File 'lib/mongocore/query.rb', line 111

def all
  fetch(:to_a).map{|d| modelize(d)}
end

#as_json(o = {}) ⇒ Object

JSON format



197
198
199
# File 'lib/mongocore/query.rb', line 197

def as_json(o = {})
  all
end

#countObject

Count. Returns the number of documents as an integer



89
90
91
# File 'lib/mongocore/query.rb', line 89

def count
  counter || fetch(:count)
end

#counter(s = , c = ) ⇒ Object

Check if there’s a corresponding counter for this count



94
95
96
# File 'lib/mongocore/query.rb', line 94

def counter(s = @options[:source], c = @options[:chain])
  s.send(%{#{@colname}#{c.present? ? "_#{c.join('_')}" : ''}_count}) rescue nil
end

#cursorObject

Cursor



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/mongocore/query.rb', line 54

def cursor
  o = @options.dup

  # Remove blank options
  o.delete(:skip) if o[:skip] < 1
  o.delete(:limit) if o[:limit] < 1
  o.delete(:sort) if o[:sort].empty?
  o.delete(:projection) if o[:projection].empty?

  # Return view
  @collection.find(@query, o)
end

#deleteObject

Delete



84
85
86
# File 'lib/mongocore/query.rb', line 84

def delete
  @collection.delete_one(@query).ok?
end

#each(&block) ⇒ Object

Each



152
153
154
# File 'lib/mongocore/query.rb', line 152

def each(&block)
  cursor.each{|r| yield(modelize(r))}
end

#each_with_index(&block) ⇒ Object

Each with index



157
158
159
# File 'lib/mongocore/query.rb', line 157

def each_with_index(&block)
  cursor.each_with_index{|r, n| yield(modelize(r), n)}
end

#each_with_object(obj, &block) ⇒ Object

Each with object



162
163
164
# File 'lib/mongocore/query.rb', line 162

def each_with_object(obj, &block)
  cursor.each_with_object(obj){|r, o| yield(modelize(r), o)}
end

#fetch(t) ⇒ Object

Fetch docs, pass type :first, :to_a or :count



144
145
146
147
148
149
# File 'lib/mongocore/query.rb', line 144

def fetch(t)
  cache.get(t) if Mongocore.cache

  # Fetch from mongodb and add to cache
  cursor.send(t).tap{|r| cache.set(t, r) if Mongocore.cache}
end

#find(q = {}, o = {}) ⇒ Object Also known as: where

Find. Returns a Mongocore::Query



43
44
45
# File 'lib/mongocore/query.rb', line 43

def find(q = {}, o = {})
  self.class.new(@model, @query.merge(hashify(q)), @options.merge(o))
end

#first(*args) ⇒ Object

Return first document



99
100
101
# File 'lib/mongocore/query.rb', line 99

def first(*args)
  modelize(find(*args).fetch(:first))
end

#hashify(q) ⇒ Object

Convert string query to hash



49
50
51
# File 'lib/mongocore/query.rb', line 49

def hashify(q)
  q.is_a?(Hash) ? q : {:_id => q}
end

#insert(a) ⇒ Object

Insert



68
69
70
# File 'lib/mongocore/query.rb', line 68

def insert(a)
  @collection.insert_one(a.delete_if{|k, v| v.nil?})
end

#keyObject

Cache key



202
203
204
# File 'lib/mongocore/query.rb', line 202

def key
  @key ||= "#{@model}#{@query.sort}#{@options.values}"
end

#last(*args) ⇒ Object

Return last document Uses the opposite of the Mongocore.sort setting



105
106
107
108
# File 'lib/mongocore/query.rb', line 105

def last(*args)
  a = Mongocore.sort.any? ? Mongocore.sort.dup : {:_id => 1}
  sort(a.each{|k, v| a[k] = v * -1}).limit(1).first(*args)
end

#limit(n = 1) ⇒ Object

Limit



178
179
180
181
# File 'lib/mongocore/query.rb', line 178

def limit(n = 1)
  @options[:limit] = n
  find(@query, @options)
end

#map(&block) ⇒ Object

Map



167
168
169
# File 'lib/mongocore/query.rb', line 167

def map(&block)
  cursor.map{|r| yield(modelize(r))}
end

#modelize(doc) ⇒ Object

BSON::Document to model



139
140
141
# File 'lib/mongocore/query.rb', line 139

def modelize(doc)
  doc ? @model.new(doc.to_hash) : nil
end

#paginate(o = {}) ⇒ Object

Paginate



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

def paginate(o = {})
  # Get total count before applying pagination
  total = fetch(:count)

  # Set page, defaults to 1
  o[:page] = o[:page].to_i
  o[:page] = 1 if o[:page] < 1

  # Set results per page, defaults to 20 in Mongocore.per_page setting
  o[:per_page] = o[:per_page].to_i
  o[:per_page] = Mongocore.per_page if o[:per_page] < 1

  # Skip results
  @options[:skip] = o[:per_page] * (o[:page] - 1)

  # Apply limit
  @options[:limit] = o[:per_page]

  # Fetch the result as array
  all.tap{|r| r.total = total}
end

#projection(o = {}) ⇒ Object Also known as: fields

Projection



190
191
192
193
# File 'lib/mongocore/query.rb', line 190

def projection(o = {})
  @options[:projection].merge!(o)
  find(@query, @options)
end

#skip(n = 0) ⇒ Object

Skip



184
185
186
187
# File 'lib/mongocore/query.rb', line 184

def skip(n = 0)
  @options[:skip] = n
  find(@query, @options)
end

#sort(o = {}) ⇒ Object

Sort



172
173
174
175
# File 'lib/mongocore/query.rb', line 172

def sort(o = {})
  (@options[:sort] ||= {}).merge!(o)
  find(@query, @options)
end

#update(a) ⇒ Object

Update



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

def update(a)
  # We do $set on non nil, $unset on nil
  u = {
    :$set => a.select{|k, v| !v.nil?}, :$unset => a.select{|k, v| v.nil?}
  }.delete_if{|k, v| v.empty?}

  # Update the collection
  @collection.update_one(@query, u, :upsert => true)
end