Mongoid supports all ActiveRecord-style methods for persistence operations on the database.
Please note the new persistence strategy section for examples with the corresponding database
queries that would be executed.
Persistence
Create
Instantiating a new object and saving it to the database in a single call is handled with
Document.create or Document.create!. Use the latter if you wish an
exception to be raised if validation fails.
person = Person.create(:first_name => "Syd", :last_name => "Vicious")
person = Person.create!(:first_name => "Emmanuel", :last_name => "Zorg")
Save
Saving a document to the database involves using Document#save or Document#save!.
Use the latter if you wish an exception to be raised if validation fails.
person = Person.new(:first_name => "Syd", :last_name => "Vicious")
person.save # or person.upsert
person = Person.new(:first_name => "Emmanuel", :last_name => "Zorg")
person.save!
Updating Attributes
Writing new attributes to a document and saving it in a single call is handled via
Document#update_attributes and Document#update_attributes!.
Use the latter if you wish an exception to be raised if validation fails.
person = Person.new(:first_name => "Syd", :last_name => "Vicious")
person.update_attributes(:first_name => "Nancy")
person = Person.new(:first_name => "Emmanuel", :last_name => "Zorg")
person.update_attributes!(:first_name => "Nancy")
Destroy
Deleting objects from the database involves calling either Document#destroy,
Document#delete, Document.destroy_all, or Document.delete_all.
The first two will delete a single document, while the second two will delete all
documents given a supplied criteria. Note that the delete methods will ignore all defined
callbacks. These can also be called on associations.
person = Person.create(:first_name => "Syd", :last_name => "Vicious")
person.destroy
person = Person.create(:first_name => "Syd", :last_name => "Vicious")
person.delete
Person.destroy_all(:conditions => { :first_name => "Syd", :last_name => "Vicious" })
Person.delete_all(:conditions => { :first_name => "Syd", :last_name => "Vicious" })
person.addresses.delete_all
person.addresses.destroy_all(:conditions => { :street => "Bond St" })
Persisting in Safe Mode
Even though Mongoid provides the global configuration option for persisting
in safe mode, if you are using the default you may use safe mode on a per
query basis. Just prepend a safely in front of your persistence
command:
Person.safely.create(:title => "King")
Person.safely.delete_all
person.safely.save
person.safely.destroy
Explicit Modifiers
Mongoid supports explicit $inc modification.
person = Person.find(id)
person.inc(:score, 100)
person.safely.inc(:score, 100) # Update in safe mode.
Persistence Strategies and Underlying DB Queries
For all following examples, the following models will be used:
class Person
include Mongoid::Document
field :first_name
field :middle_initial
field :last_name
embeds_one :email
embeds_many :addresses
end
class Address
include Mongoid::Document
field :street
field :post_code
field :state
embedded_in :person, :inverse_of => :addresses
end
class Email
include Mongoid::Document
field :address
embedded_in :person, :inverse_of => :email
end
Saving New Records
Scenario: Saving a new root document. This will perform an insert on the MongoDB
collection with all the fields on the document:
In Mongoid:
Scenario: Saving a new root document with new children. This will perform an insert on the MongoDB collection with all the fields on the document and its children, no matter where the save call was executed from:
In Mongoid:
Scenario: Saving a new embeds_one on an existing root document. This will perform an atomic update on the root document with the new embedded attributes. The save must be called from the child in this case:
In Mongoid:
Scenario: Saving a new embeds_many on an existing root document. This will perform an atomic push on the root document embedded array with the new embedded attributes. The save must be called from the child in this case:
In Mongoid:
In Mongoid:
person = Person.new(:first_name => "Dudley")
person.save
The MongoDB query:
db.people.insert({ "first_name" : "Dudley" }, true);
Scenario: Saving a new root document with new children. This will perform an insert on the MongoDB collection with all the fields on the document and its children, no matter where the save call was executed from:
In Mongoid:
person = Person.new(:first_name => "Dudley")
address = Address.new(:street => "Upper Street")
person.addresses << address
person.save # or address.save will yield same result.
The MongoDB query:
db.people.insert(
{ "first_name" : "Dudley", "addresses" : [ { "street" : "Upper Street" } ] },
true
);
Scenario: Saving a new embeds_one on an existing root document. This will perform an atomic update on the root document with the new embedded attributes. The save must be called from the child in this case:
In Mongoid:
person = Person.where(:first_name => "Dudley").first
email = Email.new(:address => "dudley@moore.com")
person.email = email
email.save
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
db.people.update(
{ "_id" : "4baa56f1230048567300485c" },
{ "$set" : { "email" : { "address" : "dudley@moore.com" } } },
false,
true
);
Scenario: Saving a new embeds_many on an existing root document. This will perform an atomic push on the root document embedded array with the new embedded attributes. The save must be called from the child in this case:
In Mongoid:
person = Person.where(:first_name => "Dudley").first
address = Address.new(:street => "Upper Street")
person.addresses << address
address.save
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
db.people.update(
{ "_id" : "4baa56f1230048567300485c" },
{ "$push" : { "addresses" : { "street" : "Upper Street" } } },
false,
true
);
Updating Existing Records
Updating existing records leverages Mongoid's dirty attributes module to only persist what
has changed on the documents. In all cases the save must be called on the document that has
been updated. (This will change in subsequent releases to check the entire tree.)
Scenario: Updating a root document. This will perform an atomic update on the dirty attributes on the model:
In Mongoid:
Scenario: Updating an existing embeds_one. This will perform an atomic update on the existing embedded document.
In Mongoid:
Scenario: Updating an existing embeds_many. This will perform an atomic update on the existing embedded document based on its position in the array.
In Mongoid:
Scenario: Updating a root document. This will perform an atomic update on the dirty attributes on the model:
In Mongoid:
person = Person.where(:first_name => "Dudley").first
person.last_name = "Moore"
person.save
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
db.people.update(
{ "_id" : "4baa56f1230048567300485c" },
{ "$set" : { "last_name" : "Moore" } },
false,
true
);
Scenario: Updating an existing embeds_one. This will perform an atomic update on the existing embedded document.
In Mongoid:
person = Person.where(:first_name => "Dudley").first
email = person.email
email.address = "dudley@moore.org"
email.save
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
db.people.update(
{ "_id" : "4baa56f1230048567300485c" },
{ "$set" : { "email.address" : "dudley@moore.org" } },
false,
true
);
Scenario: Updating an existing embeds_many. This will perform an atomic update on the existing embedded document based on its position in the array.
In Mongoid:
person = Person.where(:first_name => "Dudley").first
address = person.addresses.first
address.street = "Clerkenwell Road"
address.save
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
db.people.update(
{ "_id" : "4baa56f1230048567300485c" },
{ "$set" : { "addresses.0.street" : "Clerkenwell Road" } },
false,
true
);
Mixed Persistence
Note that when Mongoid persists, it looks at the document the persistence command was
executed and does an atomic update of all of its updates, as well as any changes embedded
below it in the hierarchy. This is handy for operating on the entire tree, and getting
a single database call for the changes. Note that as of beta8, deletion does not work in
this context, it has to be done separately.
Scenario: Updating a root document, a child document, and adding a new child.
In Mongoid:
Scenario: Updating a root document, a child document, and adding a new child.
In Mongoid:
person = Person.where(:first_name => "Dudley").first
person.last_name = "Moore"
person.email.address = "d.moore@gmail.com"
person.addresses.build(:street => "Upper Street")
person.save
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
db.people.update(
{ "_id" : "4baa56f1230048567300485c" },
{
"$set" :
{ "last_name" : "Moore", "email.address" : "d.moore@gmail.com" },
"$push" :
{ "addresses" : { "street" : "Upper Street" } }
},
false,
true
);
Deleting Records
Scenario: Deleting an existing root document. This will perform a remove
on the MongoDB collection with the document's id
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
Scenario: Deleting an existing embeds_one. This will perform an atomic unset on the embedded document.
In Mongoid:
Scenario: Deleting an existing document in an embeds_many. This will perform an atomic pull on the existing embedded document in the array.
In Mongoid:
(Assume person.id = "4baa56f1230048567300485c")
(Assume address.id = "4baa56f1230048567300485d")
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
person = Person.where(:first_name => "Dudley").first
person.delete # also destroy works here.
The MongoDB query:
db.people.remove({ "_id" : "4baa56f1230048567300485c" }, true);
Scenario: Deleting an existing embeds_one. This will perform an atomic unset on the embedded document.
In Mongoid:
person = Person.where(:first_name => "Dudley").first
email = person.email
email.delete # or destroy
The MongoDB query: (Assume person.id = "4baa56f1230048567300485c")
db.people.update(
{ "_id" : "4baa56f1230048567300485c" },
{ "$unset" : { "email" : true } },
false,
true
);
Scenario: Deleting an existing document in an embeds_many. This will perform an atomic pull on the existing embedded document in the array.
In Mongoid:
person = Person.where(:first_name => "Dudley").first
address = person.addresses.first
address.delete # or destroy
The MongoDB query:
(Assume person.id = "4baa56f1230048567300485c")
(Assume address.id = "4baa56f1230048567300485d")
db.people.update(
{ "_id" : "4baa56f1230048567300485c" },
{ "$pull" : { "addresses" : { "_id" : "4baa56f1230048567300485d" } } },
false,
true
);