| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Mongoose::Join; |
|
2
|
|
|
|
|
|
|
$Mongoose::Join::VERSION = '2.01'; |
|
3
|
1
|
|
|
1
|
|
7
|
use Moose; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
8
|
|
|
4
|
1
|
|
|
1
|
|
5730
|
use Moose::Util::TypeConstraints; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
7
|
|
|
5
|
1
|
|
|
1
|
|
1809
|
use Moose::Meta::TypeConstraint::Parameterizable; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
37
|
|
|
6
|
1
|
|
|
1
|
|
5
|
use Moose::Meta::TypeConstraint::Registry; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
22
|
|
|
7
|
1
|
|
|
1
|
|
4
|
use Tie::IxHash; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
220
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new; |
|
10
|
|
|
|
|
|
|
$REGISTRY->add_type_constraint( |
|
11
|
|
|
|
|
|
|
Moose::Meta::TypeConstraint::Parameterizable->new( |
|
12
|
|
|
|
|
|
|
name => 'Mongoose::Join', |
|
13
|
|
|
|
|
|
|
package_defined_in => __PACKAGE__, |
|
14
|
|
|
|
|
|
|
parent => find_type_constraint('Item'), |
|
15
|
|
|
|
|
|
|
constraint => sub { die 'constrained' }, |
|
16
|
|
|
|
|
|
|
constraint_generator => sub { |
|
17
|
|
|
|
|
|
|
my $type_parameter = shift; |
|
18
|
|
|
|
|
|
|
sub { return {} }; |
|
19
|
|
|
|
|
|
|
} |
|
20
|
|
|
|
|
|
|
) |
|
21
|
|
|
|
|
|
|
); |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
Moose::Util::TypeConstraints::add_parameterizable_type( $REGISTRY->get_type_constraint('Mongoose::Join') ); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
has 'class' => ( is => 'rw', isa => 'Str' ); |
|
26
|
|
|
|
|
|
|
has 'field' => ( is => 'rw', isa => 'Str' ); |
|
27
|
|
|
|
|
|
|
has 'with_class' => ( is => 'rw', isa => 'Str' ); |
|
28
|
|
|
|
|
|
|
has '_with_collection_name' => ( is => 'rw', isa => 'Str' ); |
|
29
|
|
|
|
|
|
|
has 'parent' => ( is => 'rw', isa => 'BSON::OID' ); |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# once the object is expanded, it has children too |
|
32
|
|
|
|
|
|
|
has 'children' => ( is => 'rw', isa => 'ArrayRef', default => sub{[]} ); |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# before being saved, objects are stored in this buffer |
|
35
|
|
|
|
|
|
|
has 'buffer' => ( is => 'rw', isa => 'HashRef', default => sub { {} } ); |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# deleting happens at a later moment, meanwhile delete candidates are here |
|
38
|
|
|
|
|
|
|
has 'delete_buffer' => ( is => 'rw', isa => 'HashRef', default => sub { {} } ); |
|
39
|
|
|
|
|
|
|
|
|
40
|
1
|
|
|
1
|
|
6
|
use Scalar::Util qw/refaddr/; |
|
|
1
|
|
|
|
|
10
|
|
|
|
1
|
|
|
|
|
1208
|
|
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub add { |
|
43
|
0
|
|
|
0
|
1
|
|
my ( $self, @objs ) = @_; |
|
44
|
0
|
|
|
|
|
|
for my $obj (@objs) { |
|
45
|
0
|
|
|
|
|
|
$self->buffer->{ refaddr $obj } = $obj; |
|
46
|
|
|
|
|
|
|
} |
|
47
|
0
|
|
|
|
|
|
@objs; |
|
48
|
|
|
|
|
|
|
} |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub remove { |
|
51
|
0
|
|
|
0
|
1
|
|
my ( $self, @objs ) = @_; |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# if the collection is live, remove from memory |
|
54
|
0
|
0
|
|
|
|
|
if( my $buffer = $self->buffer ) { |
|
55
|
0
|
|
|
|
|
|
for my $obj (@objs) { |
|
56
|
0
|
0
|
|
|
|
|
next unless defined $obj; |
|
57
|
0
|
|
|
|
|
|
delete $buffer->{ refaddr $obj }; |
|
58
|
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# children get cleaned too |
|
62
|
0
|
0
|
|
|
|
|
if( defined ( my $children = $self->children ) ) { |
|
63
|
0
|
|
|
|
|
|
for my $obj (@objs) { |
|
64
|
0
|
|
|
|
|
|
my $id = $obj->_id; |
|
65
|
0
|
0
|
|
|
|
|
next unless defined $id; |
|
66
|
|
|
|
|
|
|
$self->children([ |
|
67
|
0
|
|
|
|
|
|
grep { $_->id ne $id } _build_rel( @{$children} ) |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
]); |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# save action for later (when save is called) |
|
73
|
0
|
0
|
|
|
|
|
my $delete_buffer = defined $self->delete_buffer |
|
74
|
|
|
|
|
|
|
? $self->delete_buffer |
|
75
|
|
|
|
|
|
|
: $self->delete_buffer({}); |
|
76
|
0
|
|
|
|
|
|
for my $obj (@objs) { |
|
77
|
0
|
|
|
|
|
|
$delete_buffer->{ refaddr $obj } = $obj; |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub collection { |
|
82
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
83
|
0
|
0
|
|
|
|
|
defined $self->with_class |
|
84
|
|
|
|
|
|
|
and return $self->with_class->collection; |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub with_collection_name { |
|
88
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
89
|
0
|
0
|
|
|
|
|
defined $self->_with_collection_name |
|
90
|
|
|
|
|
|
|
and return $self->_with_collection_name; |
|
91
|
|
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
|
$self->_with_collection_name( Mongoose->class_config($self->with_class)->{collection_name} ); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
0
|
|
|
sub _insert { #TODO insert and commit |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub _save { |
|
99
|
0
|
|
|
0
|
|
|
my ( $self, $parent, @scope ) = @_; |
|
100
|
|
|
|
|
|
|
|
|
101
|
0
|
|
|
|
|
|
my $children = delete $self->{children}; |
|
102
|
0
|
0
|
|
|
|
|
if( ref $children eq 'Mongoose::Join' ) { |
|
103
|
0
|
|
|
|
|
|
$children = $children->children; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
0
|
0
|
|
|
|
|
my @objs = _build_rel( @{$children ||[]} ); |
|
|
0
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
my $collection_name = $self->with_collection_name; |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# load buffers |
|
110
|
0
|
|
|
|
|
|
my $buffer = delete $self->{buffer}; |
|
111
|
0
|
|
|
|
|
|
my $delete_buffer = delete $self->{delete_buffer}; |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# save buffered children |
|
114
|
0
|
|
|
|
|
|
for ( keys %{ $buffer } ) { |
|
|
0
|
|
|
|
|
|
|
|
115
|
0
|
|
|
|
|
|
my $obj = delete $buffer->{$_}; |
|
116
|
0
|
0
|
|
|
|
|
next if exists $delete_buffer->{ refaddr $obj }; |
|
117
|
0
|
|
|
|
|
|
$obj->save( @scope ); |
|
118
|
0
|
|
|
|
|
|
push @objs, _build_rel({ '$ref' => $collection_name, '$id' => $obj->_id }); |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# adjust |
|
122
|
0
|
|
|
|
|
|
$self->buffer( $buffer ); # restore the list |
|
123
|
0
|
|
|
|
|
|
$self->delete_buffer({}); |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# make sure unique children is saved |
|
126
|
0
|
|
|
|
|
|
my %unique = map { $_->id => $_ } @objs; |
|
|
0
|
|
|
|
|
|
|
|
127
|
0
|
|
|
|
|
|
@objs = values %unique; |
|
128
|
0
|
|
|
|
|
|
$self->children( \@objs ); |
|
129
|
0
|
|
|
|
|
|
return @objs; |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub _children_refs { |
|
133
|
0
|
|
|
0
|
|
|
my ($self)=@_; |
|
134
|
0
|
|
|
|
|
|
my @found; |
|
135
|
|
|
|
|
|
|
$self->find->each( sub{ |
|
136
|
0
|
|
|
0
|
|
|
push @found, _build_rel({ '$ref' => $_[0]->_collection_name, '$id' => $_[0]->{_id} }); |
|
137
|
0
|
|
|
|
|
|
}); |
|
138
|
0
|
|
|
|
|
|
return @found; |
|
139
|
|
|
|
|
|
|
} |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub find { |
|
142
|
0
|
|
|
0
|
1
|
|
my ( $self, $opts, @scope ) = @_; |
|
143
|
0
|
|
|
|
|
|
my $class = $self->with_class; |
|
144
|
0
|
|
0
|
|
|
|
$opts ||= {}; |
|
145
|
0
|
|
|
|
|
|
my $children = $self->children; |
|
146
|
0
|
0
|
|
|
|
|
if( ref $children eq 'Mongoose::Join' ) { |
|
147
|
0
|
|
|
|
|
|
$children = $children->children; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
0
|
0
|
|
|
|
|
my @children = map { $_->id } _build_rel( @{$children ||[]} ); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
|
|
151
|
0
|
|
|
|
|
|
$opts->{_id} = { '$in' => \@children }; |
|
152
|
0
|
|
|
|
|
|
return $class->find( $opts, @scope ); |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub count { |
|
156
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
157
|
0
|
|
|
|
|
|
$self->_call_rel_method( count => @_ ); |
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub find_one { |
|
161
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
162
|
0
|
|
|
|
|
|
$self->_call_rel_method( find_one => @_ ); |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub _call_rel_method { |
|
166
|
0
|
|
|
0
|
|
|
my ( $self, $method, $opts, @scope ) = @_; |
|
167
|
0
|
|
|
|
|
|
my $class = $self->with_class; |
|
168
|
|
|
|
|
|
|
|
|
169
|
0
|
|
0
|
|
|
|
$opts ||= {}; |
|
170
|
0
|
0
|
|
|
|
|
$opts->{_id} = { '$in' => [ map { $_->id } _build_rel( @{$self->children ||[]} ) ] }; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
|
|
172
|
0
|
|
|
|
|
|
return $class->$method( $opts, @scope ); |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
0
|
|
|
0
|
1
|
|
sub first { shift->find_one } |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub query { |
|
178
|
0
|
|
|
0
|
1
|
|
my ( $self, $opts, $attrs, @scope ) = @_; |
|
179
|
0
|
|
|
|
|
|
my $class = $self->with_class; |
|
180
|
0
|
|
0
|
|
|
|
$opts ||= {}; |
|
181
|
0
|
0
|
|
|
|
|
my @children = map { $_->id } _build_rel( @{$self->children ||[]} ); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
182
|
0
|
|
|
|
|
|
$opts->{_id} = { '$in' => \@children }; |
|
183
|
0
|
|
|
|
|
|
return $class->query( $opts, $attrs, @scope ); |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub all { |
|
187
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
188
|
0
|
|
|
|
|
|
return $self->find(@_)->all; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub hash_on { |
|
192
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
193
|
0
|
|
|
|
|
|
my $key = shift; |
|
194
|
0
|
|
|
|
|
|
my %hash; |
|
195
|
|
|
|
|
|
|
map { |
|
196
|
0
|
0
|
|
|
|
|
$hash{ $_->{$key} } = $_ unless exists $hash{ $_->{$key} }; |
|
|
0
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
} $self->find(@_)->all; |
|
198
|
0
|
|
|
|
|
|
return %hash; |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub hash_array { |
|
202
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
203
|
0
|
|
|
|
|
|
my $key = shift; |
|
204
|
0
|
|
|
|
|
|
my %hash; |
|
205
|
|
|
|
|
|
|
map { |
|
206
|
0
|
|
|
|
|
|
push @{ $hash{ $_->{$key} } }, $_; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
} $self->find(@_)->all; |
|
208
|
0
|
|
|
|
|
|
return %hash; |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# make sure all refs what's expected on the MongoDB driver in use |
|
212
|
|
|
|
|
|
|
sub _build_rel { |
|
213
|
0
|
|
|
0
|
|
|
map { ref $_ eq 'BSON::DBRef' |
|
214
|
|
|
|
|
|
|
? $_ |
|
215
|
0
|
0
|
|
|
|
|
: BSON::DBRef->new( ref => $_->{'$ref'}, id => $_->{'$id'} ) |
|
216
|
|
|
|
|
|
|
} @_; |
|
217
|
|
|
|
|
|
|
} |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=head1 NAME |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Mongoose::Join - simple class relationship resolver |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
package Author; |
|
226
|
|
|
|
|
|
|
use Moose; |
|
227
|
|
|
|
|
|
|
with 'Mongoose::Document'; |
|
228
|
|
|
|
|
|
|
has 'articles' => ( |
|
229
|
|
|
|
|
|
|
is => 'rw', |
|
230
|
|
|
|
|
|
|
isa => 'Mongoose::Join[Article]', |
|
231
|
|
|
|
|
|
|
default => sub { Mongoose::Join->new( with_class => 'Article' ) } |
|
232
|
|
|
|
|
|
|
); |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
This module can be used to establish relationships |
|
237
|
|
|
|
|
|
|
between two C<Mongoose::Document> classes. It should not |
|
238
|
|
|
|
|
|
|
be used with C<Mongoose::EmbeddedDocument> classes. |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
All object relationships are stored as reference C<$id> arrays |
|
241
|
|
|
|
|
|
|
into the parent object. This translates into a slight performance hit |
|
242
|
|
|
|
|
|
|
when loading the parent class, but not as much as loading all |
|
243
|
|
|
|
|
|
|
objects at one as when using an C<ArrayRef>. |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
B<Attention>: the relationship attribute needs to be initialized to |
|
246
|
|
|
|
|
|
|
an instance of C<Mongoose::Join> before it can be used. |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=head2 Mongoose::Class |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
Take a look at L<Mongoose::Class>, it has nice syntatic sugar |
|
251
|
|
|
|
|
|
|
that does most of the initialization behind the scenes for you. |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=head1 METHODS |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=head2 add |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Add (join) a Mongoose::Document object for later saving. |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Saving the parent Mongoose::Document will save both. |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
my $author = Author->new; |
|
262
|
|
|
|
|
|
|
$author->articles->add( Article->new ); |
|
263
|
|
|
|
|
|
|
$author->save; # saves all objects |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=head2 remove |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
Delete from the relationship list. |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
my $author = Author->find_one; |
|
270
|
|
|
|
|
|
|
my $first_article = $author->articles->find_one; |
|
271
|
|
|
|
|
|
|
$author->articles->remove( $first_article ); |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head2 find |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
Run a MongoDB C<find> on the joint collection. |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# searches for articles belonging to this collection |
|
278
|
|
|
|
|
|
|
my $cursor = $author->articles->find({ title=>'foo article' }); |
|
279
|
|
|
|
|
|
|
while( my $article = $cursor->next ) { |
|
280
|
|
|
|
|
|
|
... |
|
281
|
|
|
|
|
|
|
} |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Returns a L<Mongoose::Cursor>. |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=head2 count |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
Count relations. |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=head2 find_one |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
Just like find, but returns the first row found. |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head2 first |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Alias to C<find_one> |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
$first_cd = $artist->cds->first; |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head2 all |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
Same as C<find>, but returns an ARRAY with all the results, instead |
|
302
|
|
|
|
|
|
|
of a cursor. |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
my @cds = $artist->cds->all; |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head2 hash_on |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Same as C<all>, but returns a HASH instead of an ARRAY. |
|
309
|
|
|
|
|
|
|
The hash will be indexed by the key name sent as the first parameter. |
|
310
|
|
|
|
|
|
|
The hash value contains exactly one object. In case duplicate rows |
|
311
|
|
|
|
|
|
|
with the same key value are found, the resulting hash will contain |
|
312
|
|
|
|
|
|
|
the first one found. |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# ie. returns $cds{'111888888292adf0000003'} = <CD Object>; |
|
315
|
|
|
|
|
|
|
my %cds = $artist->cds->hash_on( '_id' => { artist=>'Joe' }); |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# ie. returns $joe_cds{'Title1'} = <CD Object>; |
|
318
|
|
|
|
|
|
|
my %joe_cds = $artist->cds->hash_on( 'title' => { artist=>qr/Joe/ }); |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head2 hash_array |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Similar to C<hash_on>, but returns a hash with ALL rows found, grouped |
|
323
|
|
|
|
|
|
|
by the key. |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# ie. returns $cds{'Title1'} = [ <CD1 Object>, <CD2 Object>, ... ]; |
|
326
|
|
|
|
|
|
|
my %cds = $artist->cds->hash_array( 'title' => { artist=>'Joe' }); |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
Hash values are ARRAYREFs with 1 or more rows. |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=head2 query |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
Run a MongoDB C<query> on the joint collection. |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
=head2 collection |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
Returns the L<MongoDB::Collection> for the joint collection. |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=head2 with_collection_name |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
Return the collection name for the joint Mongoose::Document. |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=cut |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable(); |