Provided by: libmongodbx-class-perl_1.02-3_all bug

NAME

       MongoDBx::Class::Tutorial - Tutorial for using MongoDBx::Class

VERSION

       version 1.02

INTRODUCTION

       MongoDBx::Class is a flexible object relational mapper (ORM) for MongoDB databases. Before
       reading this tutorial, please read "DESCRIPTION" in MongoDBx::Class.

CREATING DOCUMENT CLASSES

       The first step towards using MongoDBx::Class is creating document classes.  Let's say your
       application is called MyApp, and that it reviews novels by popular authors. Every novel
       has a title (its name), the full name of its author, its release year, a synopsis, the
       date the novel was added to the database, a list of tags categorizing the novel, a list of
       related novels, and zero or more reviews.

       MongoDBx::Class provides you with a flexible foundation for building classes that
       represent our proposed database schema and the relationships (or "joins") between these
       classes. This foundation is provided by three modules:

       •   MongoDBx::Class::Moose - intended to be used by document classes in place of Moose. It
           provides Moose, and all needed relationship types, in the form of Moose attributes.

       •   MongoDBx::Class::Document - a Moose role intended to be consumed by document classes.
           When documents are expanded from the database, this role is applied to them and thus
           provides them some common attributes and methods.

       •   MongoDBx::Class::EmbeddedDocument - a Moose role intended to be consumed by embedded
           document classes. When embedded documents are found inside other documents and
           expanded, this role is applied to them and thus provides them some common attributes
           and methods.

       Before actually creating document classes, we need to design our schema.  The most common
       question to tackle when designing a schema is when and how to use references, and when to
       simply embed documents. Refer to
       http://www.mongodb.org/display/DOCS/Schema+Design#SchemaDesign-Embedvs.Reference
       <http://www.mongodb.org/display/DOCS/Schema+Design#SchemaDesign-Embedvs.Reference> for
       some information about schema design in MongoDB.

       Our database schema will be like this:

       •   Every novel will be represented by a document in the 'novels' collection.

       •   An author's name will be stored in the novel's document as an embedded document that
           has first and last names, and possibly a middle name.

       •   The synopsis of the novel will be stored as a standalone document in the 'synopsis'
           collection, and will simply reference the novel with a 'novel' attribute.

       •   The date and time the novel was added to the database will be stored as a W3C
           formatted string which will automatically be converted to a DateTime object (see
           MongoDBx::Class::ParsedAttribute::DateTime or read further for the rationale).

       •   The list of tags will be stored in the novel document as an array of embedded
           documents.

       •   The list of related novels will be stored in the novel document as an array of
           database references to other novels.

       •   The reviews for every novel are stored as standalone documents in the 'reviews'
           collection, and will simply reference the novel with a 'novel' attribute.

       Let's look at a possible JSON representation of a novel - "The Valley of Fear" by Sir
       Arthur Conan Doyle:

               # in the 'novels' collection
               {
                       "_id": ObjectId("4cbca90d576fad5916790100"),
                       "title": "The Valley of Fear",
                       "year": 1914,
                       "author": {
                               "first_name": "Arthur",
                               "middle_name": "Conan",
                               "last_name": "Doyle"
                       },
                       "added": "2010-01-11T22:12:44+02:00",
                       "tags": [
                               { "category": "mystery", "subcategory": "thriller" },
                               { "category": "mystery", "subcategory": "detective" },
                               { "category": "crime", "subcategory": "fiction" }
                       ],
                       "related_novels": [
                               { "$ref": "novels", "$id": ObjectId("4cbca90d3a41e35916720100") },
                               { "$ref": "novels", "$id": ObjectId("4cbca90d44d8c959167a0100") },
                               { "$ref": "novels", "$id": ObjectId("4cbca90d486bbf59166f0100") }
                       ]
               }

               # in the 'synopsis' collection
               {
                       "_id": ObjectId("4cbca90d699e9a5916670100"),
                       "novel": { "$ref": "novels", "$id": ObjectId("4cbca90d576fad5916790100") },
                       "text": "The Valley of Fear is the final Sherlock Holmes novel by Sir Arthur Conan Doyle. The story was first published in the Strand Magazine between September 1914 and May 1915. The first book edition was published in New York on 27 February 1915."
               }

               # in the 'reviews' collection
               {
                       "_id": ObjectId("4cbca90dfbb2945916740100"),
                       "novel": { "$ref": "novels", "$id": ObjectId("4cbca90d576fad5916790100") },
                       "reviewer": "Some Guy",
                       "text": "I really liked it!",
                       "score": 5
               },
               {
                       "_id": ObjectId("4cbca90e0ad57b5916f50100"),
                       "novel": { "$ref": "novels", "$id": ObjectId("4cbca90d576fad5916790100") },
                       "reviewer": "Some Other Guy",
                       "text": "It was okay.",
                       "score": 3
               },
               {
                       "_id": ObjectId("4cbca90e0b9c175916c60100"),
                       "novel": { "$ref": "novels", "$id": ObjectId("4cbca90d576fad5916790100") },
                       "reviewer": "Totally Different Guy",
                       "text": "Man, that just sucked!",
                       "score": 1
               }

       We now need to translate this structure to MongoDBx::Class document classes.  As mentioned
       before, document classes are Moose classes, but instead of using Moose, they use
       MongoDBx::Class::Moose. We'll start with the document class representing novels:

               package MyApp::Schema::Novel;

               use MongoDBx::Class::Moose;
               use namespace::autoclean;

               with 'MongoDBx::Class::Document';

               has 'title' => (is => 'ro', isa => 'Str', required => 1, writer => 'set_title');

               holds_one 'author' => (is => 'ro', isa => 'MyApp::Schema::PersonName', required => 1, writer => 'set_author');

               has 'year' => (is => 'ro', isa => 'Int', predicate => 'has_year', writer => 'set_year');

               has 'added' => (is => 'ro', isa => 'DateTime', traits => ['Parsed'], required => 1);

               has 'review_count' => (is => 'rw', isa => 'Int', traits => ['Transient'], builder => '_build_review_count');

               holds_many 'tags' => (is => 'ro', isa => 'MyApp::Schema::Tag', predicate => 'has_tags');

               joins_one 'synopsis' => (is => 'ro', isa => 'Synopsis', coll => 'synopsis', ref => 'novel');

               has_many 'related_novels' => (is => 'ro', isa => 'Novel', predicate => 'has_related_novels', writer => 'set_related_novels', clearer => 'clear_related_novels');

               joins_many 'reviews' => (is => 'ro', isa => 'Review', coll => 'reviews', ref => 'novel');

               sub _build_review_count { shift->reviews->count }

               sub print_related_novels {
                       my $self = shift;

                       foreach my $other_novel ($self->related_novels) {
                               print $other_novel->title, ', ',
                                     $other_novel->year, ', ',
                                     $other_novel->author->name, "\n";
                       }
               }

               around 'reviews' => sub {
                       my ($orig, $self) = (shift, shift);

                       my $cursor = $self->$orig;

                       return $cursor->sort([ year => -1, title => 1, 'author.last_name' => 1 ]);
               };

               __PACKAGE__->meta->make_immutable;

       Aside from standard Moose usage, we've used some of MongoDBx::Class' built-in relationship
       types. Head over to MongoDBx::Class::Moose for a list of provided relationship types and
       how they translate to database entries.

       In this example, we've used the "holds_one" relationship to denote that a Novel document
       entirely holds one embedded PersonName sub-document. We've used "holds_many" to have Novel
       documents entirely hold Tag documents.  We've also used "joins_one" to easily find a
       novel's synopsis, located in the synopsis collection. "joins_many" was used to easily find
       all Review documents located in the reviews collection. Finally, we've used "has_many" for
       the list of references to related novels.

       You will notice that when using the "holds_one" and "holds_many" relationship types, we've
       given the full package names to the "isa" option (such as MyApp::Schema::PersonName),
       while in other relationship types, we've given the class names only (such as 'Synopsis').
       This inconsistency is only temporary, and will change in future versions, so keep your
       finger on the pulse.

       Of particular interest is the 'added' attribute, for which we've added the
       <Parsed|MongoDBx::Class::AttributeTraits::Parsed> attribute trait (automatically provided
       with MongoDBx::Class). When adding this trait to an attribute, MongoDBx::Class looks for a
       module implementing the MongoDBx::Class::ParsedAttribute role named like the 'isa' option
       of the attribute. In our example, MongoDBx::Class will look for
       MongoDBx::Class::ParsedAttribute::DateTime. However, if you're creating your own
       ParsedAttribute classes, you need to also pass the 'parser' option.  For example:

               has 'added' => (is => 'ro', isa => 'DateTime', traits => ['Parsed'], parser => 'MyApp::ParsedAttribute::MyCoolDateTimeParser', required => 1);

       The 'Parsed' trait means that the parser is responsible for expanding this attribute from
       the database when loading a document, and for collapsing the attribute when saving to the
       database. This is similar to DBIx::Class' InflateColumn family of classes from the SQL
       world. You might ask yourself why we're using a special DateTime parser here, even though
       MongoDB natively supports DateTime objects.  The following paragraph is taken from
       MongoDBx::Class::ParsedAttribute::DateTime's documentation):

               While the Perl L<MongoDB> driver already supports L<DateTime> objects
               natively, due to a bug with MongoDB, you can't save dates earlier than
               the UNIX epoch. This module overcomes this limitation by simply saving
               dates as strings and automatically turning them into DateTime objects
               (and vica-versa). The DateTime strings are formatted by the L<DateTime::Format::W3CDTF>
               module, which parses dates in the format recommended by the W3C. This is
               good for web apps, and also makes it easier to edit dates from the
               MongoDB shell. But most importantly, it also allows sorting by date.

       Also note the 'review_count' attribute, which has the 'Transient' trait.  This trait means
       the attribute is not to be saved in the database, even though it is one of the document's
       attributes. This is useful for calculated attributes, or any supporting attributes you add
       to a document class whose state should not be saved. You should note that if for some
       reason a document in the database does have an attribute marked as transient in the
       document's class (for example if you added it to the document manually), the value of this
       attribute will also be ignored when the document is read from the database.

       As you can see, the "joins_many" relationship creates a one-to-many relationship between
       one document to one or more other documents which can be considered "child documents". In
       this example, there is a one-to-many relationship between a 'novel' document and one or
       more 'review' documents.  A "joins_many" relationship is implemented with a cursor. For
       example, calling the "reviews()" method on a "Novel" object will generally return a
       MongoDBx::Class::Cursor object for a "find()" query that searches for documents in the
       'reviews' collection, whose 'novel' attribute references the "Novel" document. In the
       "Novel" class above, you will notice the "reviews()" method is also modified with Moose's
       "around" method modifier. This example illustrates the fact that "joins_many" is
       implemented with a cursor. Suppose you know you will always want to call "reviews()" and
       get the child documents sorted by date (or other fields).  The above modification simply
       sorts the cursor before returning it to the caller. Of course, this is merely an example
       of the things you can do with the "joins_many" relationship.

       Continuing on, lets create our two embedded document classes. We'll start with PersonName:

               package MyApp::Schema::PersonName;

               use MongoDBx::Class::Moose;
               use namespace::autoclean;

               with 'MongoDBx::Class::EmbeddedDocument';

               has 'first_name' => (is => 'ro', isa => 'Str', required => 1, writer => 'set_first_name');

               has 'middle_name' => (is => 'ro', isa => 'Str', predicate => 'has_middle_name', writer => 'set_middle_name');

               has 'last_name' => (is => 'ro', isa => 'Str', required => 1, writer => 'set_last_name');

               sub name {
                       my $self = shift;

                       my $name = $self->first_name;
                       $name .= ' '.$self->middle_name if $self->has_middle_name;
                       $name .= ' '.$self->last_name;

                       return $name;
               }

               __PACKAGE__->meta->make_immutable;

       This is a very simple class, with no relationships. We use the "name()" method to easily
       print a person's full name.

       On to the Tag document class:

               package MyApp::Schema::Tag;

               use MongoDBx::Class::Moose;
               use namespace::autoclean;

               with 'MongoDBx::Class::EmbeddedDocument';

               has 'category' => (is => 'ro', isa => 'Str', required => 1);

               has 'subcategory' => (is => 'ro', isa => 'Str', required => 1);

               __PACKAGE__->meta->make_immutable;

       Again, this is a very simple example. Embedded documents will often be as simple as that.

       We have two document classes left. The first is the Synopsis class:

               package MyApp::Schema::Synopsis;

               use MongoDBx::Class::Moose;
               use namespace::autoclean;

               with 'MongoDBx::Class::Document';

               belongs_to 'novel' => (is => 'ro', isa => 'Novel', required => 1);

               has 'text' => (is => 'ro', isa => 'Str', writer => 'set_text', required => 1);

               __PACKAGE__->meta->make_immutable;

       Here, we've used "belongs_to" to signify a Synopsis document belongs to a Novel document.
       Every Synopsis document has a 'novel' attribute which references the parent Novel
       document.

       Only the Review class is left:

               package MyApp::Schema::Review;

               use MongoDBx::Class::Moose;
               use namespace::autoclean;

               with 'MongoDBx::Class::Document';

               belongs_to 'novel' => (is => 'ro', isa => 'Novel', required => 1);

               has 'reviewer' => (is => 'ro', isa => 'Str', required => 1);

               has 'text' => (is => 'ro', isa => 'Str', required => 1);

               has 'score' => (is => 'ro', isa => 'Int', predicate => 'has_score');

               __PACKAGE__->meta->make_immutable;

       That wraps up our document classes. Before we continue, it is important to note that
       MongoDBx::Class' ability to identify the class of a document is currently reliant on the
       existance of a '_class' attribute in every document in the database (as described in
       "CAVEATS AND THINGS TO CONSIDER" in MongoDBx::Class).  So, looking at the JSON
       representations from before, we need to modify the representations like so:

               # in the 'novels' collection
               {
                       "_id": ObjectId("4cbca90d576fad5916790100"),
                       "_class": "Novel",
                       "title": "The Valley of Fear",
                       "year": 1914,
                       "author": {
                               "first_name": "Arthur",
                               "middle_name": "Conan",
                               "last_name": "Doyle"
                       },
                       "added": "2010-01-11T22:12:44+02:00",
                       "tags": [
                               { "category": "mystery", "subcategory": "thriller" },
                               { "category": "mystery", "subcategory": "detective" },
                               { "category": "crime", "subcategory": "fiction" }
                       ],
                       "related_novels": [
                               { "$ref": "novels", "$id": ObjectId("4cbca90d3a41e35916720100") },
                               { "$ref": "novels", "$id": ObjectId("4cbca90d44d8c959167a0100") },
                               { "$ref": "novels", "$id": ObjectId("4cbca90d486bbf59166f0100") }
                       ]
               }

               # in the 'synopsis' collection
               {
                       "_id": ObjectId("4cbca90d699e9a5916670100"),
                       "_class": "Synopsis",
                       "novel": { "$ref": "novels", "$id": ObjectId("4cbca90d576fad5916790100") },
                       "text": "The Valley of Fear is the final Sherlock Holmes novel by Sir Arthur Conan Doyle. The story was first published in the Strand Magazine between September 1914 and May 1915. The first book edition was published in New York on 27 February 1915."
               }

               # in the 'reviews' collection
               {
                       "_id": ObjectId("4cbca90dfbb2945916740100"),
                       "_class": "Review",
                       "novel": { "$ref": "novels", "$id": ObjectId("4cbca90d576fad5916790100") },
                       "reviewer": "Some Guy",
                       "text": "I really liked it!",
                       "score": 5
               },
               {
                       "_id": ObjectId("4cbca90e0ad57b5916f50100"),
                       "_class": "Review",
                       "novel": { "$ref": "novels", "$id": ObjectId("4cbca90d576fad5916790100") },
                       "reviewer": "Some Other Guy",
                       "text": "It was okay.",
                       "score": 3
               },
               {
                       "_id": ObjectId("4cbca90e0b9c175916c60100"),
                       "_class": "Review",
                       "novel": { "$ref": "novels", "$id": ObjectId("4cbca90d576fad5916790100") },
                       "reviewer": "Totally Different Guy",
                       "text": "Man, that just sucked!",
                       "score": 1
               }

       You will notice that it is not required to add the '_class' attribute to embedded
       documents, only to standalone documents. The reason for the '_class' requirement is the
       fact that MongoDBx::Class doesn't enforce one collection for every document class. Every
       collection can have documents of one or more classes, and documents of the same class can
       be stored in one or more collections, even databases.

LOADING MongoDBx::Class AND CONNECTING TO A MongoDB SERVER

       The next step is loading the schema we've just created, and connecting to a MongoDB
       server:

               my $dbx = MongoDBx::Class->new(namespace => 'MyApp::Schema');

       We need to pass the namespace of our schema to MongoDBx::Class. It will attempt to
       automatically load every document class under that namespace, and will return a
       MongoDBx::Class object back.

       We then initiate a connection to a server:

               my $conn = $dbx->connect();

       We don't pass anything to the "connect()" method, so it attempts to connect to a MongoDB
       server running on 'localhost', on the default 27017 port. We can connect to a specific
       server like so:

               my $conn = $dbx->connect(host => $host, port => $port);

       The connect method accepts any of the options that the "new()" method in
       MongoDB::Connection accepts, plus the new 'safe' boolean attribute.  Passing a true value
       for this attribute causes MongoDBx::Class to automatically enable the 'pass' option to all
       insert/update/delete operations performed on the database, so we don't need to pass "{
       safe => 1 }" to the "insert()", "update()" methods, etc. The safe option is actually
       required in order to autoamtically expand/collapse documents, so you'd probably want to
       enable it, but it is kept disabled by default for compatibility with the original MongoDB
       module.

       The "connect()" method returns a MongoDBx::Class::Connection object.

       NOTE: versions prior to 0.7 stored the returned connection object as the 'conn' attribute
       of the $dbx variable. This behavior has been dropped in version 0.7 in order to be
       consistent with MongoDB and allowing multiple connections.

       Now that we have our connection object, we can get a database object:

               $conn->get_database('whatever'); # also simply $conn->whatever

INSERTING DOCUMENTS

       Now the we've loaded our schema and connected to a server, we can start using
       MongoDBx::Class. Basically, our usage will not differ greatly from direct MongoDB usage,
       as MonogDBx::Class simply extends MongoDB. The biggest difference between directly using
       MongoDB and using MongoDBx::Class, is the automatic expanding and collapsing of documents.
       Documents are automatically expanded when inserting documents only if the "safe" option is
       on, as mentioned in the previous section.

       Let's create a novel document:

               my $db = $conn->get_database('myapp');
               my $novels_coll = $db->get_collection('novels');

               my $novel = $novels_coll->insert({
                       _class => 'Novel',
                       title => 'The Valley of Fear',
                       year => 1914,
                       author => {
                               first_name => 'Arthur',
                               middle_name => 'Conan',
                               last_name => 'Doyle',
                       },
                       added => DateTime->now(time_zone => 'Asia/Jerusalem'),
                       tags => [
                               { category => 'mystery', subcategory => 'thriller' },
                               { category => 'mystery', subcategory => 'detective' },
                               { category => 'crime', subcategory => 'fiction' },
                       ],
               });

       Notice that when inserting the novel document, we've directly inserted the PersonName
       embedded document and the Tags embedded documents as hash-refs.

       This insert, which was safe (since the 'safe' attribute of our connection object had a
       true value), returns the novel document after expansion:

               $novel->author->name; # prints 'Arthur Conan Doyle'

       If the insert was unsafe, we'd just get the MongoDB::OID of the document back. But note
       that you can't get the OID object and immediately attempt to load the document with it, as
       you can't predict the order in which MongoDB will perform asynchronous operations.

       Lets insert our synopsis now:

               my $synopsis = $db->synopsis->insert({
                       _class => 'Synopsis',
                       novel => $novel,
                       text => "The Valley of Fear is the final Sherlock Holmes novel by Sir Arthur Conan Doyle. The story was first published in the Strand Magazine between September 1914 and May 1915. The first book edition was published in New York on 27 February 1915.",
               });

       Notice how we've passed the $novel object directly as the 'novel' attribute.  When
       inserting, MongoDBx::Class will automatically save it as a DBRef object for us.

       Now for our reviews:

               my @reviews = $conn->get_collection('reviews')->batch_insert([
                       {
                               _class => 'Review',
                               novel => $novel,
                               reviewer => 'Some Guy',
                               text => 'I really liked it!',
                               score => 5,
                       },
                       {
                               _class => 'Review',
                               novel => $novel,
                               reviewer => 'Some Other Guy',
                               text => 'It was okay.',
                               score => 3,
                       },
                       {
                               _class => 'Review',
                               novel => $novel,
                               reviewer => 'Totally Different Guy',
                               text => 'Man, that just sucked!',
                               score => 1,
                       }
               ]);

               my ($total_score, $avg_score) = (0, 0);
               foreach (@reviews) {
                       $total_score += $_->score || 0;
               }
               $avg_score = $total_score / scalar(@reviews);
               print $avg_score; # prints 3

       If we now run "$novel->reviews()", we'd get a MongoDBx::Class::Cursor back. And since
       we've created a method modification in the Novel class on this method, this cursor will
       also be sorted.

               foreach ($novel->reviews) {
                       # $_ is now a MyApp::Schema::Review object
                       print $_->score;
               }

SEARCHING DOCUMENTS

       MongoDBx::Class adds automatic expansion to document searching, plus some convenient
       shortcuts. Say we've received the ID of a novel document as input, and we want to load it.
       With MongoDB, we'd probably do:

               $db->novels->find_one({ _id => MongoDB::OID->new(value => $oid) })

       With MongoDBx::Class, we can just do:

               $db->novels->find_one($oid);

       And $oid can either be the string ID, or a MongoDB::OID object.

       If the document is found, and has the '_class' attribute, then it will be automatically
       expanded.

               my $novel = $db->novels->find_one($oid)
                       || die "Oh my god I can't find this, kill me, kill me now";

               print $novel->author->name; # again, prints 'Arthur Conan Doyle'

       Let's search for reviews written by a certain reviewer:

               my $cursor = $db->reviews->find({ reviewer => 'Some Guy' })->sort({ score => -1 }); # the `find` method also has two synonyms: `query` and `search`

       This gives a MongoDBx::Class::Cursor back:

               print $cursor->count; # prints 1

               while (my $review = $cursor->next) {
                       print $review->novel->title, "\n";
               }

       Sorting documents is easier. We can sort by a list of ordered attributes like so:

               $cursor->sort([ attr1 => 1, attr2 => 1, attr3 => -1 ]);

UPDATING DOCUMENTS

       Updating documents is much easier with MongoDBx::Class. There are two ways to update
       documents in MongoDBx::Class:

       • The older, MongoDB way of using the "update()" method in MongoDBx::Class::Collection.
         This is now mostly used to update multiple documents at once.

       • The new, MongoDBx::Class way of using the "update()" method provided to document classes
         by MongoDBx::Class::Document. This is used to update a specific document.

       Let's take a look at the first way. Suppose we want to cheat and update all reviews for
       "The Valley of Fear" with a score of five:

               $db->reviews->update({ 'novel.$id' => $novel->_id }, { '$set' => { score => 5 } }, { multiple => 1 }); # updates are by default singular, so we add the 'multiple' option

       This is exactly like using MongoDB::Collection directly. If we're updating a specific
       document we've already loaded, however, MongoDBx::Class provides a much more comfortable
       way. Instead of doing:

               $db->novels->update({ _id => $novel->_id }, { ... })

       We can do:

               $novel->update({ year => 1915 });

       This will effectively invoke a '$set' update like this:

               $db->novels->update({ _id => $novel->_id }, { '$set' => { year => 1915 } });

       But this isn't really the Moose way of doing things, so MongoDBx::Class gives us yet
       another way of updating a document:

               $novel->set_year(1915); # we can do this because we've added a 'writer' option to the 'year' attribute
               $novel->update;

       When invoking "update()" on a document object with no arguments, a "snapshot" of the
       document is taken, and the following update is effectively performed:

               $db->novels->update({ _id => $novel->_id }, { title => "The Valley of Fear", year => 1915, ... });

       When we pass arguments to the "update()" method (there are two arguments we can pass, the
       hash-ref of updates to perform, and the standard options hash-ref we know from the
       original "update()" method in MongoDB::Collection), MongoDBx::Class simply performs a
       '$set' update on the passed hash-ref attributes only. So doing this:

               $novel->set_year(1915);
               $novel->update({ title => 'The Valley of Fearrrrrr' });

       Will only result in the 'title' attribute being updated, not the year attribute.

       Updating embedded documents is similarly easy:

               $novel->author->set_first_name('Sir Arthur');
               $novel->update;

REMOVING DOCUMENTS

       Removing documents with MongoDBx::Class is very easy. Having the document object, simply
       call:

               $novel->remove;

       Or:

               $novel->delete;

       And this novel document will be removed from the database. Note, however, that the delete
       operation does not cascade, so only the novel document is deleted. The synopsis and
       reviews are not deleted, and you have to do so manually.

       You can still use the original "remove()" method on collections, now mostly to remove
       multiple documents:

               $db->get_collection('reviews')->remove({ 'novel.$id' => $novel->_id }); # removes are by default multiple

FAQ

   Can I use more than one database?
       Yes, you can use as many databases as you like and use the same document classes across
       them:

               my $data_db = $conn->get_database('myapp_data');
               my $user_db = $conn->get_database('myapp_users');

   Can I define different document classes to different databases?
       There currently isn't a way to define individual schemas for different databases. You can,
       however, "split" your schema. For example, if your application has a data DB and a user
       DB, you can put all the document classes of the data DB under MyApp::Schema::Data, and all
       the document classes of the user DB under MyApp::Schema::User.

   What if I want to use the asynchronous AnyMongo driver instead?
       Currently, MongoDBx::Class only supports the official MongoDB driver, but support for
       AnyMongo is planned.

   What if I have attributes I don't want to save in the database?
       MongoDBx::Class does not provide an option like that yet, but will probably do so in
       upcoming versions.

   I'm not getting document objects but just the document hash-refs, what gives?
       If, either when searching for documents or creating/updating documents, you are not
       receiving expanded document objects back but only the document hash-refs when
       searching/updating, or the documents' MongoDB::OIDs when inserting, there might be a few
       reasons for this:

       1. You are not using safe operations: MongoDBx::Class cannot expand documents when not
       using safe operations. Either enable the 'safe' option when inserting/updating, or enable
       the safe option globally when connecting using MongoDBx::Class's "connect()" method.
       2. The document hash-ref does not define the '_class' attribute: MongoDBx::Class cannot
       expand document without knowing to which document class the document belongs. Therefore,
       documents in the MongoDB database must have the '_class' attribute.
       3. The '_class' attribute is wrong or does not exist: If the document has the '_class'
       attribute and you're still not getting document objects back, then MongoDBx::Class
       probably can't find the document class. This might be because the class name is wrong, or
       the class was not found when loading MongoDBx::Class. If that is the case, you might wanna
       take a look at the "search_dirs" attribute of MongoDBx::Class.

   Who framed Roger Rabbit?
       I framed Roger Rabbit!

WRAP UP

       You now know how you can use MongoDBx::Class in your applications, and make MongoDB act
       like a relational database, without sacrificing its NoSQL nature and special features.

       Before using MongoDBx::Class, please take into account that its alpha software, and is not
       ready yet for production use. If you find bugs, please report them in the usual channels
       (see "BUGS" in MongoDBx::Class).

AUTHOR

       Ido Perlmuter, "<ido at ido50.net>"

SUPPORT

       You can find documentation for this module with the perldoc command.

               perldoc MongoDBx::Class::Tutorial

SEE ALSO

       MongoDBx::Class, MongoDB, <http://www.mongodb.org/>.

LICENSE AND COPYRIGHT

       Copyright 2010-2012 Ido Perlmuter.

       This program is free software; you can redistribute it and/or modify it under the terms of
       either: the GNU General Public License as published by the Free Software Foundation; or
       the Artistic License.

       See http://dev.perl.org/licenses/ for more information.