NAME¶
MongoDBx::Class::Moose - Extends Moose with common relationships for
MongoDBx::Class documents
VERSION¶
version 1.030002
PROVIDES¶
Moose
SYNOPSIS¶
# create a document class
package MyApp::Schema::Novel;
use MongoDBx::Class::Moose; # use this instead of 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);
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 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;
DESCRIPTION¶
This module provides some relationship types (i.e. database references) for
MongoDB documents and embedded documents, in the form of Moose attributes. It
also provides everything Moose provides, and so is to replace "use
Moose" when creating document classes.
RELATIONSHIP TYPES¶
This module provides the following relationship types. The differences between
different relationships stem from the different ways in which references can
be represented in the database.
belongs_to¶
Specifies that the document has an attribute which references another,
supposedly parent, document. The reference is in the form documented by
MongoDBx::Class::Reference.
belongs_to 'parent' => (is => 'ro', isa => 'Article', required => 1)
In the database, this relationship is represented in the referencing document
like this:
{ ... parent => { '$ref' => 'coll_name', '$id' => $mongo_oid } ... }
Calling "parent()" on the referencing document returns the parent
document after expansion:
$doc->parent->title;
has_one¶
Specifies that the document has an attribute which references another document.
The reference is in the form documented by MongoDBx::Class::Reference. This is
entirely equivalent to "belongs_to", the two are provided merely for
convenience, the difference is purely semantic.
has_many¶
Specifies that the document has an attribute which holds a list (array) of
references to other documents. These references are in the form documented by
MongoDBx::Class::Reference.
has_many 'related_articles' => (is => 'ro', isa => 'Article', predicate => 'has_related_articles')
In the database, this relationship is represented in the referencing document
like this:
{ ... related_articles => [{ '$ref' => 'coll_name', '$id' => $mongo_oid_1 }, { '$ref' => 'other_coll_name', '$id' => $mongo_oid_2 }] ... }
Calling "related_articles()" on the referencing document returns an
array of all referenced documents, after expansion:
foreach ($doc->related_articles) {
print $_->title, "\n";
}
holds_one¶
Specifies that the document has an attribute which holds an embedded document
(a.k.a sub-document) in its entirety. The embedded document is represented by
a class that "does" MongoDBx::Class::EmbeddedDocument.
holds_one 'author' => (is => 'ro', isa => 'MyApp::Schema::PersonName', required => 1)
Note that the "holds_one" relationship has the unfortunate constraint
of having to pass the full package name of the foreign document (e.g.
MyApp::Schema::PersonName above), whereas other relationship types (except
"holds_many" which has the same constraint) require the class name
only (e.g. Novel).
In the database, this relationship is represented in the referencing (i.e.
holding) document like this:
{ ... author => { first_name => 'Arthur', middle_name => 'Conan', last_name => 'Doyle' } ... }
Calling "author()" on the referencing document returns the embedded
document, after expansion:
$doc->author->first_name; # returns 'Arthur'
holds_many¶
Specifies that the document has an attribute which holds a list (array) of
embedded documents (a.k.a sub-documents) in their entirety. These embedded
documents are represented by a class that "does"
MongoDBx::Class::EmbeddedDocument.
holds_many 'tags' => (is => 'ro', isa => 'MyApp::Schema::Tag', predicate => 'has_tags')
Note that the "holds_many" relationship has the unfortunate constraint
of having to pass the full package name of the foreign document (e.g.
MyApp::Schema::Tag above), whereas other relationship types (except
"holds_one" which has the same constraint) require the class name
only (e.g. Novel).
In the database, this relationship is represented in the referencing (i.e.
holding) document like this:
{ ... tags => [ { category => 'mystery', subcategory => 'thriller' }, { category => 'mystery', subcategory => 'detective' } ] ... }
defines_many¶
Specifies that the document has an attribute which holds a hash (a.k.a
associative array or dictionary) of embedded documents in their entirety.
These embedded documents are represented by a class that "does"
MongoDBx::Class::EmbeddedDocument.
defines_many 'things' => (is => 'ro', isa => 'MyApp::Schema::Thing', predicate => 'has_things');
When calling "things()" on a document, a hash-ref is returned (not a
hash!).
Like "holds_many" and "holds_one", this relationship has the
unfortunate constraint of having to pass the full package name of the foreign
document (e.g. MyApp::Schema::Thing above), whereas other relationship types
require the class name only (e.g. Novel).
In the database, this relationship is represented in the referencing (i.e.
holding) document like this:
{ ...
things => {
"mine" => { _class => 'MyApp::Schema::Thing', ... },
"his" => { _class => 'MyApp::Schema::Thing', ... },
"hers" => { _class => 'MyApp::Schema::Thing', ... },
}
...
}
joins_one¶
Specifies that the document is referenced by one other document. The reference
in the other document to this document is in the form documented by
MongoDBx::Class::Reference. This "pseudo-attribute" requires two new
options: 'coll', with the name of the collection in which the referencing
document is located, and 'ref', with the name of the attribute which is
referencing the document. If 'coll' isn't provided, the referencing document
is searched in the same collection.
joins_one 'synopsis' => (is => 'ro', isa => 'Synopsis', coll => 'synopsis', ref => 'novel')
In the database, this relationship is represented in the referencing document
(located in the 'synopsis' collection) like this:
{ ... novel => { '$ref' => 'novels', '$id' => $mongo_oid } ... }
When calling "synopsis()" on a Novel document, a
"find_one()" query is performed like so:
$db->get_collection('synopsis')->find_one({ 'novel.$id' => $doc->_id })
Note that passing a 'required' option to "joins_one" has no effect at
all, the existence of the referencing document is never enforced, so
"undef" can be returned.
joins_many¶
Specifies that the document is referenced by other documents. The references in
the other document to this document are in the form documented by
MongoDBx::Class::Reference. This "pseudo-attribute" requires two new
options: 'coll', with the name of the collection in which the referencing
documents are located, and 'ref', with the name of the attribute which is
referncing the document. If 'coll' isn't provided, the referencing documents
are searched in the same collection.
joins_many 'reviews' => (is => 'ro', isa => 'Review', coll => 'reviews', ref => 'novel')
In the database, this relationship is represented in the referencing documents
(located in the 'reviews' collection) like this:
{ ... novel => { '$ref' => 'novels', '$id' => $mongo_oid } ... }
When calling "reviews()" on a Novel document, a "find()"
query is performed like so:
$db->get_collection('reviews')->find({ 'novel.$id' => $doc->_id })
And thus a MongoDBx::Class::Cursor is returned.
Note that passing the 'required' option to "joins_many" has no effect
at all, and the existance of referncing documents is never enforced, so the
cursor can have a count of zero.
AUTHOR¶
Ido Perlmuter, "<ido at ido50.net>"
BUGS¶
Please report any bugs or feature requests to "bug-mongodbx-class at
rt.cpan.org", or through the web interface at
<
http://rt.cpan.org/NoAuth/ReportBug.html?Queue=MongoDBx-Class>. I will
be notified, and then you'll automatically be notified of progress on your bug
as I make changes.
SUPPORT¶
You can find documentation for this module with the perldoc command.
perldoc MongoDBx::Class::Moose
You can also look for information at:
- •
- RT: CPAN's request tracker
<http://rt.cpan.org/NoAuth/Bugs.html?Dist=MongoDBx::Class>
- •
- AnnoCPAN: Annotated CPAN documentation
<http://annocpan.org/dist/MongoDBx::Class>
- •
- CPAN Ratings
<http://cpanratings.perl.org/d/MongoDBx::Class>
- •
- Search CPAN
<http://search.cpan.org/dist/MongoDBx::Class/>
SEE ALSO¶
MongoDBx::Class::Document, MongoDBx::Class::EmbeddedDocument, Moose.
LICENSE AND COPYRIGHT¶
Copyright 2010-2014 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.