Class: Perpetuity::MongoDB

Inherits:
Object
  • Object
show all
Defined in:
lib/perpetuity/mongodb.rb,
lib/perpetuity/mongodb/index.rb,
lib/perpetuity/mongodb/query.rb,
lib/perpetuity/mongodb/serializer.rb,
lib/perpetuity/mongodb/query_union.rb,
lib/perpetuity/mongodb/query_attribute.rb,
lib/perpetuity/mongodb/query_expression.rb,
lib/perpetuity/mongodb/query_intersection.rb

Defined Under Namespace

Classes: Index, Query, QueryAttribute, QueryExpression, QueryIntersection, QueryUnion, Serializer

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ MongoDB

Returns a new instance of MongoDB.



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/perpetuity/mongodb.rb', line 14

def initialize options
  @host       = options.fetch(:host, 'localhost')
  @port       = options.fetch(:port, 27017)
  @db         = options.fetch(:db)
  @pool_size  = options.fetch(:pool_size, 5)
  @username   = options[:username]
  @password   = options[:password]
  @session    = nil
  @indexes    = Hash.new { |hash, key| hash[key] = active_indexes(key) }
  @connected  = false
end

Instance Attribute Details

#dbObject

Returns the value of attribute db.



12
13
14
# File 'lib/perpetuity/mongodb.rb', line 12

def db
  @db
end

#hostObject

Returns the value of attribute host.



12
13
14
# File 'lib/perpetuity/mongodb.rb', line 12

def host
  @host
end

#passwordObject

Returns the value of attribute password.



12
13
14
# File 'lib/perpetuity/mongodb.rb', line 12

def password
  @password
end

#pool_sizeObject

Returns the value of attribute pool_size.



12
13
14
# File 'lib/perpetuity/mongodb.rb', line 12

def pool_size
  @pool_size
end

#portObject

Returns the value of attribute port.



12
13
14
# File 'lib/perpetuity/mongodb.rb', line 12

def port
  @port
end

#usernameObject

Returns the value of attribute username.



12
13
14
# File 'lib/perpetuity/mongodb.rb', line 12

def username
  @username
end

Instance Method Details

#activate_index!(index) ⇒ Object



193
194
195
196
197
198
199
200
# File 'lib/perpetuity/mongodb.rb', line 193

def activate_index! index
  attribute = index.attribute.to_s
  order = index.order == :ascending ? 1 : -1
  unique = index.unique?

  collection(index.collection).indexes.create({attribute => order}, unique: unique)
  index.activate!
end

#active_indexes(klass) ⇒ Object



184
185
186
187
188
189
190
191
# File 'lib/perpetuity/mongodb.rb', line 184

def active_indexes klass
  collection(klass).indexes.map do |index|
    key = index['key'].keys.first
    direction = index['key'][key]
    unique = index['unique']
    Index.new(klass, Attribute.new(key), order: Index::KEY_ORDERS[direction], unique: unique)
  end.to_set
end

#all(klass) ⇒ Object



140
141
142
# File 'lib/perpetuity/mongodb.rb', line 140

def all klass
  retrieve klass, nil_query, {}
end

#can_serialize?(value) ⇒ Boolean

Returns:

  • (Boolean)


152
153
154
# File 'lib/perpetuity/mongodb.rb', line 152

def can_serialize? value
  serializable_types.include? value.class
end

#collection(klass) ⇒ Object



46
47
48
# File 'lib/perpetuity/mongodb.rb', line 46

def collection klass
  database[klass.to_s]
end

#connectObject



30
31
32
33
34
# File 'lib/perpetuity/mongodb.rb', line 30

def connect
  session.(@username, @password) if @username and @password
  @connected = true
  session
end

#connected?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/perpetuity/mongodb.rb', line 36

def connected?
  !!@connected
end

#count(klass, criteria = nil_query, &block) ⇒ Object



71
72
73
74
# File 'lib/perpetuity/mongodb.rb', line 71

def count klass, criteria=nil_query, &block
  q = block_given? ? query(&block).to_db : criteria.to_db
  collection(klass).find(q).count
end

#databaseObject



40
41
42
43
44
# File 'lib/perpetuity/mongodb.rb', line 40

def database
  session.use db
  connect unless connected?
  session
end

#delete(id, klass) ⇒ Object



144
145
146
# File 'lib/perpetuity/mongodb.rb', line 144

def delete id, klass
  collection(klass.to_s).find("_id" => id).remove
end

#delete_all(klass) ⇒ Object



76
77
78
# File 'lib/perpetuity/mongodb.rb', line 76

def delete_all klass
  collection(klass.to_s).find.remove_all
end

#drop_collection(to_be_dropped) ⇒ Object



156
157
158
# File 'lib/perpetuity/mongodb.rb', line 156

def drop_collection to_be_dropped
  collection(to_be_dropped.to_s).drop
end

#find(klass, id) ⇒ Object



108
109
110
# File 'lib/perpetuity/mongodb.rb', line 108

def find klass, id
  collection(klass).find(to_bson_id(_id: id))
end

#first(klass) ⇒ Object



80
81
82
83
84
85
# File 'lib/perpetuity/mongodb.rb', line 80

def first klass
  document = collection(klass.to_s).find.limit(1).first
  document[:id] = document.delete("_id")

  document
end

#increment(klass, id, attribute, count = 1) ⇒ Object



104
105
106
# File 'lib/perpetuity/mongodb.rb', line 104

def increment klass, id, attribute, count=1
  find(klass, id).update '$inc' => { attribute => count }
end

#index(klass, attribute, options = {}) ⇒ Object



172
173
174
175
176
177
178
# File 'lib/perpetuity/mongodb.rb', line 172

def index klass, attribute, options={}
  @indexes[klass] ||= Set.new

  index = Index.new(klass, attribute, options)
  @indexes[klass] << index 
  index
end

#indexes(klass) ⇒ Object



180
181
182
# File 'lib/perpetuity/mongodb.rb', line 180

def indexes klass
  @indexes[klass]
end

#insert(klass, objects) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/perpetuity/mongodb.rb', line 50

def insert klass, objects
  if objects.is_a? Array
    objects.each do |object|
      object[:_id] = object.delete(:id) || Moped::BSON::ObjectId.new
    end

    collection(klass).insert objects
    objects.map { |object| object[:_id] }
  else
    insert(klass, [objects]).first
  end

rescue Moped::Errors::OperationFailure => e
  if e.message =~ /duplicate key/
    e.message =~ /\$(\w+)_\d.*dup key: { : (.*) }/
    key = $1
    value = $2.gsub("\\\"", "\"")
    raise DuplicateKeyError, "Tried to insert #{klass} with duplicate unique index: #{key} => #{value}"
  end
end

#negate_query(&block) ⇒ Object



168
169
170
# File 'lib/perpetuity/mongodb.rb', line 168

def negate_query &block
  Query.new(&block).negate
end

#nil_queryObject



164
165
166
# File 'lib/perpetuity/mongodb.rb', line 164

def nil_query
  NilQuery.new
end

#query(&block) ⇒ Object



160
161
162
# File 'lib/perpetuity/mongodb.rb', line 160

def query &block
  Query.new(&block)
end

#remove_index(index) ⇒ Object



202
203
204
205
206
207
208
209
210
211
# File 'lib/perpetuity/mongodb.rb', line 202

def remove_index index
  coll = collection(index.collection)
  db_indexes = coll.indexes.select do |db_index|
    db_index['name'] =~ /\A#{index.attribute}/
  end.map { |idx| idx['key'] }

  if db_indexes.any?
    collection(index.collection).indexes.drop db_indexes.first
  end
end

#retrieve(klass, criteria, options = {}) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/perpetuity/mongodb.rb', line 87

def retrieve klass, criteria, options = {}
  # MongoDB uses '_id' as its ID field.
  criteria = to_bson_id(criteria.to_db)

  skipped = options.fetch(:skip) { 0 }

  query = collection(klass.to_s)
            .find(criteria)
            .skip(skipped)
            .limit(options[:limit])

  sort(query, options).map do |document|
    document[:id] = document.delete("_id")
    document
  end
end

#serialize(object, mapper) ⇒ Object



213
214
215
# File 'lib/perpetuity/mongodb.rb', line 213

def serialize object, mapper
  Serializer.new(mapper).serialize object
end

#sessionObject



26
27
28
# File 'lib/perpetuity/mongodb.rb', line 26

def session
  @session ||= Moped::Session.new(["#{host}:#{port}"]).with(safe: true)
end

#sort(query, options) ⇒ Object



129
130
131
132
133
134
135
136
137
138
# File 'lib/perpetuity/mongodb.rb', line 129

def sort query, options
  return query unless options[:attribute] &&
                      options[:direction]

  sort_orders = { ascending: 1, descending: -1 }
  sort_field = options[:attribute]
  sort_direction = options[:direction]
  sort_criteria = { sort_field => sort_orders[sort_direction] }
  query.sort(sort_criteria)
end

#to_bson_id(criteria) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/perpetuity/mongodb.rb', line 112

def to_bson_id criteria
  criteria = criteria.dup

  # Check for both string and symbol ID in criteria
  if criteria.has_key?('id')
    criteria['_id'] = Moped::BSON::ObjectId(criteria['id']) rescue criteria['id']
    criteria.delete 'id'
  end

  if criteria.has_key?(:id)
    criteria[:_id] = Moped::BSON::ObjectId(criteria[:id]) rescue criteria[:id]
    criteria.delete :id
  end

  criteria
end

#unserialize(data, mapper) ⇒ Object



217
218
219
# File 'lib/perpetuity/mongodb.rb', line 217

def unserialize data, mapper
  Serializer.new(mapper).unserialize data
end

#update(klass, id, new_data) ⇒ Object



148
149
150
# File 'lib/perpetuity/mongodb.rb', line 148

def update klass, id, new_data
  find(klass, id).update(new_data)
end