Persistence

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.

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:
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:
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:
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")
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
);

Fork me on GitHub!