Skip to content

Commit

Permalink
improved implementation of group, sum, min, max; improved test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
njlg committed Sep 22, 2015
1 parent 363f0af commit c5c5ab0
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 22 deletions.
20 changes: 12 additions & 8 deletions lib/Rethinkdb/Query.pm
Original file line number Diff line number Diff line change
Expand Up @@ -414,17 +414,21 @@ sub sample {
sub group {
my $self = shift;
my $args = [@_];
my $optargs = {};

my $reductor;
if ( ref $args->[ $#{$args} ] ) {
$reductor = pop @{$args};
$args = [ $args, $reductor ];
if ( ref $args->[ $#{$args} ] eq 'HASH' ) {
$optargs = pop @{$args};
}

if( ref $args->[0] && ref $args->[0] ne 'CODE' ) {
$args = Rethinkdb::Util->_wrap_func($args->[0]);
}

my $q = Rethinkdb::Query->new(
_parent => $self,
_type => $self->_termType->group,
args => $args
args => $args,
optargs => $optargs
);

return $q;
Expand Down Expand Up @@ -469,7 +473,7 @@ sub count {

sub sum {
my $self = shift;
my $args = {@_};
my $args = [@_];

my $q = Rethinkdb::Query->new(
_parent => $self,
Expand All @@ -495,7 +499,7 @@ sub avg {

sub min {
my $self = shift;
my $args = {@_};
my $args = [@_];

my $q = Rethinkdb::Query->new(
_parent => $self,
Expand All @@ -508,7 +512,7 @@ sub min {

sub max {
my $self = shift;
my $args = {@_};
my $args = [@_];

my $q = Rethinkdb::Query->new(
_parent => $self,
Expand Down
145 changes: 132 additions & 13 deletions t/aggregation.t
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,49 @@ r->table('dc')->insert(
]
)->run;

# group
$res = r->table('marvel')->group('age')->avg('strength')->run;

is $res->type, 1, 'Correct response type';
is_deeply $res->response,
{
'1035' => '2035',
'35' => '543.166666666667',
'135' => '1035',
'20' => '200',
},
'Correct response';

# group by more than one field (we have to use `group_format=>'raw'`)
$res = r->table('marvel')->group( 'age', 'active' )
->run( { group_format => 'raw' } );

is_deeply $res->response->{data}->[0][0], [ 20, 0 ];
is $res->response->{data}->[0][1][0]->{superhero}, 'Spider-Man';

# group using a function
$res = r->table('marvel')->group(
sub {
my $row = shift;
return $row->pluck( 'age', 'active' );
}
)->run( { group_format => 'raw' } );

is_deeply $res->response->{data}->[0][0], { age => 20, active => 0 };
is $res->response->{data}->[0][1][0]->{superhero}, 'Spider-Man';

# group `multi=true`
# r.table('games2').group(r.row['matches'].keys(), multi=True).run()
$res = r->table('marvel')
->group( r->row->bracket('dc_buddies'), { multi => r->true } )->run;

is $#{ $res->response->{Batman} }, 3, 'Correct `multi=true` response';

# ungroup
$res = r->table('marvel')->group('age')->avg('strength')->ungroup->run;

is_deeply [ sort keys %{ $res->response->[0] } ], [ 'group', 'reduction' ];

# reduce
$res = r->table('marvel')->map( r->row->bracket('age') )->reduce(
sub ($$) {
Expand Down Expand Up @@ -199,6 +242,84 @@ $res = r->table('marvel')->count(
is $res->type, 1, 'Correct response type';
is $res->response, '4', 'Correct number of documents';

# sum
$res = r->expr( [ 3, 5, 7 ] )->sum->run($conn);

is $res->response, 15, 'Correct response';

# sum - document attributes
$res = r->table('marvel')->sum('age')->run;

is $res->response, 1400, 'Correct response';

# sum - documents based on function
$res = r->table('marvel')->sum(
sub {
my $row = shift;
return $row->bracket('strength')->mul( $row->bracket('active') );
}
)->run;

is $res->response, 6132, 'Correct response';

# avg
$res = r->expr( [ 3, 5, 7 ] )->avg->run($conn);

is $res->response, 5, 'Correct response';

# avg - document attributes
$res = r->table('marvel')->avg('age')->run;

is substr( $res->response, 0, 7 ), '155.555', 'Correct response';

# avg - documents based on function
$res = r->table('marvel')->avg(
sub {
my $row = shift;
return $row->bracket('strength')->mul( $row->bracket('active') );
}
)->run;

is substr( $res->response, 0, 7 ), '681.333', 'Correct response';

# min
$res = r->expr( [ 3, 5, 7 ] )->min->run($conn);

is $res->response, 3, 'Correct response';

# min - document attributes
$res = r->table('marvel')->min('age')->run;
is $res->response->{age}, 20, 'Correct response';

# min - documents based on function
$res = r->table('marvel')->min(
sub {
my $row = shift;
return $row->bracket('strength')->mul( $row->bracket('active') );
}
)->run;

is $res->response->{age}, 20, 'Correct response';

# max
$res = r->expr( [ 3, 5, 7 ] )->max->run($conn);

is $res->response, 7, 'Correct response';

# max - document attributes
$res = r->table('marvel')->max('age')->run;
is $res->response->{age}, 1035, 'Correct response';

# max - documents based on function
$res = r->table('marvel')->max(
sub {
my $row = shift;
return $row->bracket('strength')->mul( $row->bracket('active') );
}
)->run;

is $res->response->{age}, 1035, 'Correct response';

# distinct (on table)
$res = r->table('marvel')->distinct->run;

Expand All @@ -211,26 +332,24 @@ $res = r->expr( [ 1, 1, 1, 1, 1, 2, 3 ] )->distinct->run($conn);
is $res->type, 1, 'Correct response type';
is scalar @{ $res->response }, 3, 'Correct number of documents';

# group_by
$res = r->table('marvel')->group('age')->avg('strength')->run;

is $res->type, 1, 'Correct response type';
is_deeply $res->response,
{
'1035' => '2035',
'35' => '543.166666666667',
'135' => '1035',
'20' => '200',
},
'Correct response';

# contains
$res = r->table('marvel')->get('Iron Man')->bracket('dc_buddies')
->contains('Superman')->run;

is $res->type, 1, 'Correct response type';
is $res->response, r->true, 'Correct response value';

$res = r->table('marvel')->filter(
sub {
my $hero = shift;
return r->expr( [ 'Smash', 'Size' ] )
->contains( $hero->bracket('superpower') );
}
)->bracket('superhero')->run;

is_deeply sort $res->response, [ 'Ant-Man', 'Hulk' ],
'Correct filter & contains response';

# clean up
r->db('test')->drop->run;

Expand Down
11 changes: 10 additions & 1 deletion t/control.t
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ r->table('marvel')->insert(
battles => 3,
villainDefeated => 'Mandarin',
outfits => 12,
gadget => 'Shoulder-mounted rocket launcher'
},
{
user_id => 8,
Expand All @@ -40,7 +41,8 @@ r->table('marvel')->insert(
age => 20,
victories => 24,
battles => 3,
villainDefeated => 'Green Goblin'
villainDefeated => 'Green Goblin',
gadget => 'Web-slinger'
}
]
)->run;
Expand Down Expand Up @@ -126,6 +128,13 @@ is $res->type, 2, 'Correct response type';
is_deeply [ sort { $a <=> $b } @{ $res->response } ], [ '0', '2', '13' ],
'Correct response';

$res = r->table('marvel')->map(r->row->bracket('gadget')->default)->run;

is $res->type, 2, 'Correct response type';
is_deeply [ sort @{ $res->response } ], [ undef, 'Shoulder-mounted rocket launcher', 'Web-slinger' ],
'Correct response';


# expr
$res = r->expr( { 'a' => 'b' } )->merge( { 'b' => [ 1, 2, 3 ] } )->run($conn);

Expand Down
48 changes: 48 additions & 0 deletions t/document.t
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,54 @@ $res = r->table('marvel')->get('Iron Man')->bracket('equipment')
is $res->type, 1, 'Correct response type';
is_deeply $res->response, ['oldHelm'];

# get_field
$res = r->table('marvel')->get('Iron Man')->get_field('reactorState')->run;

is $res->type, 1, 'Correct response type';
is $res->response, 'medium', 'Correct response';

$res = r->table('marvel')->get_field('superpower')->run;

is $res->type, 2, 'Correct response type';
is_deeply [sort @{$res->response}],
[
'Adamantium', 'Bio-lasers', 'Bow-n-arrow', 'God-like powers',
'Size', 'Smash', 'Spidy Sense', 'Super Strength',
],
'Correct response';

# bracket
$res = r->table('marvel')->get('Iron Man')->bracket('reactorState')->run;

is $res->type, 1, 'Correct response type';
is $res->response, 'medium', 'Correct response';

$res = r->table('marvel')->bracket('superpower')->run;

is $res->type, 2, 'Correct response type';
is_deeply [sort @{$res->response}],
[
'Adamantium', 'Bio-lasers', 'Bow-n-arrow', 'God-like powers',
'Size', 'Smash', 'Spidy Sense', 'Super Strength',
],
'Correct response';

# attr - depercated
$res = r->table('marvel')->get('Iron Man')->attr('reactorState')->run;

is $res->type, 1, 'Correct response type';
is $res->response, 'medium', 'Correct response';

$res = r->table('marvel')->attr('superpower')->run;

is $res->type, 2, 'Correct response type';
is_deeply [sort @{$res->response}],
[
'Adamantium', 'Bio-lasers', 'Bow-n-arrow', 'God-like powers',
'Size', 'Smash', 'Spidy Sense', 'Super Strength',
],
'Correct response';

# Plucks out one or more attributes from either an object or a sequence of
# objects (projection).
$res = r->table('marvel')->get('Iron Man')
Expand Down
27 changes: 27 additions & 0 deletions t/string.t
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,31 @@ isa_ok $res, 'Rethinkdb::Response';
is $res->type, 1, 'Correct status code';
is $res->response, undef, 'Correct number of updates';

# split
$res = r->expr('foo bar bax')->split->run($conn);

isa_ok $res, 'Rethinkdb::Response';
is $res->type, 1, 'Correct status code';
is_deeply $res->response, ['foo', 'bar', 'bax'], 'Correct split response';

$res = r->expr('id:0,foo:bar,stuff:good')->split(',')->run($conn);

isa_ok $res, 'Rethinkdb::Response';
is $res->type, 1, 'Correct status code';
is_deeply $res->response, ['id:0', 'foo:bar', 'stuff:good'], 'Correct split response';

# upcase
$res = r->expr('Sentence about LaTeX.')->upcase->run($conn);

isa_ok $res, 'Rethinkdb::Response';
is $res->type, 1, 'Correct status code';
is $res->response, 'SENTENCE ABOUT LATEX.', 'Correct split response';

# downcase
$res = r->expr('Sentence about LaTeX.')->downcase->run($conn);

isa_ok $res, 'Rethinkdb::Response';
is $res->type, 1, 'Correct status code';
is $res->response, 'sentence about latex.', 'Correct split response';

done_testing();

0 comments on commit c5c5ab0

Please sign in to comment.