NAME
Mojo::DB::Results::Role::MoreMethods - More methods for DB Results,
like Mojo::Pg::Results and Mojo::mysql::Results
STATUS
SYNOPSIS
use Mojo::DB::Results::Role::MoreMethods results_class => 'Mojo::Pg::Results';
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
my $name = $results->get;
my $name = $results->get(0);
my $name = $results->get(-3);
my ($name) = $results->get;
my ($name, $age, $favorite_food) = $results->get;
my ($name, $age, $favorite_food) = $results->get(0..2);
my ($name, $favorite_food) = $results->get(0, 2);
my ($name, $favorite_food) = $results->get(-3, -1);
my $name = $results->get_by_name('name');
my ($name) = $results->get_by_name('name');
my ($name, $favorite_food) = $results->get_by_name('name', 'favorite_food');
while (my ($name, $favorite_food) = $results->get('name', 'favorite_food')) {
say qq{$name's favorite food is $favorite_food};
}
# get the next row as a Mojo::Collection
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name']);
my $full_name = $results->c->join(' ');
# or get collection values by name
my $first_and_last_name = $results->c_by_name('first_name', 'last_name')->join(' ');
# get all rows as collections in a Mojo::Collection
my $full_names = $results->collections->map(sub { $_->join(' ') });
# assert that exactly one row is returned where expected (not 0, not more than one)
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
my $name = $results->one;
my ($name, $age, $favorite_food) = $results->one;
my ($name, $favorite_food) = $results->one_by_name('name', 'favorite_food');
# Flatten results into one Mojo::Collection with names of all people who like Pizza
my $results = $db->select(people => ['name'] => {favorite_food => 'Pizza'});
my $names = $results->flatten;
say 'Pizza lovers:';
say for $names->each;
# access results by a key
my $results = $db->select(people => '*');
my $results_by_name = $results->hashify('name');
# $alice_row is a hash
my $alice_row = $results_by_name->{Alice};
# access results by multiple keys with a multilevel hash
my $results_by_full_name = $results->hashify(['first_name', 'last_name']);
# $alice_smith_row is a hash
my $alice_smith_row = $results_by_full_name->{Alice}{Smith};
# collect results by a key in a Mojo::Collection behind a hash
my $results = $db->select(people => '*');
my $collections_by_name = $results->hashify_collect('name');
# $alice_collection is a Mojo::Collection of all rows with the name 'Alice' as hashes
my $alice_collection = $collections_by_name->{Alice};
# collect results by multiple keys in a Mojo::Collection behind a multilevel hash
my $collections_by_full_name = $results->hashify_collect(['first_name', 'last_name']);
# $alice_smith_row is a hash
my $alice_smith_collection = $collections_by_full_name->{Alice}{Smith};
# create a Mojo::Collection of Mojo::Collection's, where all results that share the same key
# are grouped in the same inner Mojo::Collection
my $results = $db->select(people => '*');
my $name_collections = $results->collect_by('name');
for my $name_collection ($name_collections->each) {
say 'Ages for ' . $name_collection->[0]{name};
for my $row ($name_collection->each) {
say "$row->{name} is $row->{age} years old";
}
}
DESCRIPTION
Mojo::DB::Results::Role::MoreMethods is a role that that provides
additional methods for results classes like Mojo::Pg::Results or
Mojo::mysql::Results.
Mojo::DB::Results::Role::MoreMethods requires a results class that has
at least these methods:
* array
* arrays
* columns
* hash
* hashes
HOW TO APPLY ROLE
results_class
use Mojo::DB::Results::Role::MoreMethods results_class => 'Mojo::Pg::Results';
# or multiple
use Mojo::DB::Results::Role::MoreMethods results_class => ['Mojo::Pg::Results', 'Mojo::mysql::Results'];
"results_class" allows you to apply
Mojo::DB::Results::Role::MoreMethods to one results class package by
providing the results class name, or to multiple by providing an
arrayref of results class names.
-mysql
use Mojo::DB::Results::Role::MoreMethods -mysql;
# shortcut for
use Mojo::DB::Results::Role::MoreMethods results_class => 'Mojo::mysql::Results';
-mysql is a shortcut for applying Mojo::DB::Results::Role::MoreMethods
to Mojo::mysql::Results.
This can be used with "-Pg".
-Pg
use Mojo::DB::Results::Role::MoreMethods -Pg;
# shortcut for
use Mojo::DB::Results::Role::MoreMethods results_class => 'Mojo::Pg::Results';
-Pg is a shortcut for applying Mojo::DB::Results::Role::MoreMethods to
Mojo::Pg::Results.
This can be used with "-mysql".
with_roles
# apply Mojo::Pg::Results::Role::MoreMethods
my $pg = Mojo::Pg->new(...);
my $results = $pg->db->select(people => ['name'] => {id => 123})->with_roles('+MoreMethods');
my $name = $results->get;
# apply Mojo::mysql::Results::Role::MoreMethods
my $mysql = Mojo::mysql->new(...);
my $results = $mysql->db->select(people => ['name'] => {id => 123})->with_roles('+MoreMethods');
my $name = $results->get;
# apply using any results class
my $pg = Mojo::Pg->new(...);
my $results = $pg->db->select(people => ['name'] => {id => 123})->with_roles('Mojo::DB::Results::Role::MoreMethods');
my $name = $results->get;
You may use "with_roles" in Mojo::Base to apply
Mojo::DB::Results::Role::MoreMethods to your results classes.
These roles are also available to take advantage of with_role's
shorthand + notation when using Mojo::Pg::Results or
Mojo::mysql::Results:
* Mojo::Pg::Results::Role::MoreMethods
* Mojo::mysql::Results::Role::MoreMethods
These two roles are essentially just aliases for
Mojo::DB::Results::Role::MoreMethods. They are just empty roles with
only this line:
with 'Mojo::DB::Results::Role::MoreMethods';
Mojo::DB::Role::ResultsRoles
# example from Mojo::DB::Role::ResultsRoles
use Mojo::Pg;
my $pg = Mojo::Pg->new(...)->with_roles('Mojo::DB::Role::ResultsRoles');
push @{$pg->results_roles}, 'Mojo::DB::Results::Role::MoreMethods';
my $results = $pg->db->query(...);
# $results does Mojo::DB::Results::Role::MoreMethods
Mojo::DB::Role::ResultsRoles allows roles to be applied to the results
objects returned by database APIs like Mojo::Pg or Mojo::mysql. See its
documentation for more information.
You may take advantage of with_role's shorthand + notation when using
Mojo::Pg or Mojo::mysql objects:
# short hand with_roles syntax supported for Mojo::Pg and Mojo::mysql objects
push @{$pg->results_roles}, '+MoreMethods';
METHODS
get
Be sure to call finish, such as "finish" in Mojo::Pg::Results or
"finish" in Mojo::mysql::Results, if you are not fetching all of the
possible rows.
"get" will fetch the next row from sth.
SCALAR CONTEXT
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
# return the first column
my $name = $results->get;
# same as above but specifying index
my $name = $results->get(0);
# negative indexes may be used
my $name = $results->get(-3);
# any column may be gotten with an index
my $age = $results->get(1);
When "get" is called in scalar context with no index, it will fetch the
next row from sth and return the first column requested in your query.
If an index is specified, the value corresponding to the column at that
index in the query will be used instead. A negative index may be used
just like indexing into Perl arrays.
WHILE LOOPS
# THIS IS WRONG DO NOT DO THIS.
while (my $name = $results->get) {
# broken loop...
}
Because "get" in scalar context may return undef, an empty string or a
0 as values for a column, it cannot be reliably used in while loops
(unless used in "LIST CONTEXT"). If you expect one row to be returned,
considering using "one" instead.
If you would like to use while loops with "get", consider using a while
loop in "LIST CONTEXT":
while (my ($name) = $results->get) {
say $name;
}
LIST CONTEXT
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
# return the first column
my ($name) = $results->get;
# same as above but specifying index
my ($name) = $results->get(0);
# multiple indexes may be used
my ($name, $favorite_food) = $results->get(0, 2);
# negative indexes may be used
my ($name, $favorite_food) = $results->get(-3, -1);
# get all column values
my ($name, $age, $favorite_food) = $results->get;
my @person = $results->get;
# iterate
while (my ($name, $age, $favorite_food) = $results->get) {
say qq{$name is $age years old and their favorite food is $favorite_food};
}
When "get" is called in list context with no index, it will fetch the
next row from sth and return all values for the row as a list.
Individual column values may be requested by providing indexes.
Negative indexes may also be used just like indexing into Perl arrays.
OPTIONS
You may provide options to "get" by providing an options hashref as the
first argument.
die
# dies if no next row exists
my $name = $results->get({die => 1});
my $name = $results->get({die => 1}, 0);
Dies unless there is a next row to be retrieved. See "get_or_die" for
this same behavior without needing to provide the die option.
The "die" option does nothing if "one" is provided, as "one" is a
superset of the functionality of "die".
one
# dies unless exactly one row was returned in the results
my $name = $results->get({one => 1});
my $name = $results->get({one => 1}, 0);
Dies unless exactly one row was returned in the results. See "one" for
this same behavior without needing to provide the one option.
get_by_name
Be sure to call finish, such as "finish" in Mojo::Pg::Results or
"finish" in Mojo::mysql::Results, if you are not fetching all of the
possible rows.
"get_by_name" will fetch the next row from sth.
SCALAR CONTEXT
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
# return the name column
my $name = $results->get_by_name('name');
"get_by_name" called in scalar context will fetch the next row from sth
and returns the individual value for the column corresponding to the
provided name.
WHILE LOOPS
# THIS IS WRONG DO NOT DO THIS.
while (my $name = $results->get_by_name('name')) {
# broken loop...
}
Because "get_by_name" in scalar context may return undef, an empty
string or a 0 as values for a column, it cannot be reliably used in
while loops (unless used in "LIST CONTEXT"). If you expect one row to
be returned, considering using "one_by_name" instead.
If you would like to use while loops with "get_by_name", consider using
a while loop in "LIST CONTEXT":
while (my ($name) = $results->get_by_name('name')) {
say $name;
}
LIST CONTEXT
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
# return the name column
my ($name) = $results->get_by_name('name');
# multiple names may be used
my ($name, $favorite_food) = $results->get('name', 'favorite_food');
# get all column values
my ($name, $age, $favorite_food) = $results->get_by_name('name', 'age', 'favorite_food');
# iterate
while (my ($name, $age, $favorite_food) = $results->get_by_name('name', 'age', 'favorite_food')) {
say qq{$name is $age years old and their favorite food is $favorite_food};
}
"get_by_name" fetches the next row from sth and returns the list of
values corresponding to the list of column names provided.
OPTIONS
You may provide options to "get_by_name" by providing an options
hashref as the first argument.
die
# dies if no next row exists
my $name = $results->get_by_name({die => 1});
my $name = $results->get_by_name({die => 1}, 0);
Dies unless there is a next row to be retrieved. See
"get_by_name_or_die" for this same behavior without needing to provide
the die option.
The "die" option does nothing if "one" is provided, as "one" is a
superset of the functionality of "die".
one
# dies unless exactly one row was returned in the results
my $name = $results->get({one => 1});
my $name = $results->get({one => 1}, 0);
Dies unless exactly one row was returned in the results. See
"one_by_name" for this same behavior without needing to provide the one
option.
c
Be sure to call finish, such as "finish" in Mojo::Pg::Results or
"finish" in Mojo::mysql::Results, if you are not fetching all of the
possible rows.
"c" will fetch the next row from sth.
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name']);
my $full_name = $results->c->join(' ');
# iterate
while (my $c = $results->c) {
my $full_name = $c->join(' ');
say "Full name is $full_name";
}
"c" fetches the next row from sth and returns the row as a
Mojo::Collection. If there is no next row available, undef is returned.
You may provide indexes to get just those values in the
Mojo::Collection, just as you can do with "get":
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name']);
my $full_name = $results->c(0, 2)->join(' ');
# prints "$first_name $last_name"
say $full_name;
OPTIONS
You may provide options to "c" by providing an options hashref as the
first argument.
die
# dies if no next row exists
my $person = $results->c({die => 1});
my $person = $results->c({die => 1}, 0, 2);
Dies unless there is a next row to be retrieved. See "c_or_die" for
this same behavior without needing to provide the die option.
The "die" option does nothing if "one" is provided, as "one" is a
superset of the functionality of "die".
one
# dies unless exactly one row was returned in the results
my $person = $results->c({one => 1});
my $person = $results->c({one => 1}, 0, 2);
Dies unless exactly one row was returned in the results. See "one_c"
for this same behavior without needing to provide the one option.
c_by_name
Be sure to call finish, such as "finish" in Mojo::Pg::Results or
"finish" in Mojo::mysql::Results, if you are not fetching all of the
possible rows.
"c_by_name" will fetch the next row from sth.
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name']);
my $full_name = $results->c_by_name('first_name', 'middle_name', 'last_name')->join(' ');
# iterate
while (my $c = $results->c_by_name('first_name', 'middle_name', 'last_name')) {
my $full_name = $c->join(' ');
say "Full name is $full_name";
}
"c_by_name" fetches the next row from sth and returns the values
corresponding to the provided columns for the next row as a
Mojo::Collection. If there is no next row available, undef is returned.
OPTIONS
You may provide options to "c_by_name" by providing an options hashref
as the first argument.
die
# dies if no next row exists
my $person = $results->c_by_name({die => 1}, 'first_name', 'middle_name', 'last_name');
Dies unless there is a next row to be retrieved. See "c_by_name_or_die"
for this same behavior without needing to provide the die option.
The "die" option does nothing if "one" is provided, as "one" is a
superset of the functionality of "die".
one
# dies unless exactly one row was returned in the results
my $person = $results->c({one => 1}, 'first_name', 'middle_name', 'last_name');
Dies unless exactly one row was returned in the results. See
"one_c_by_name" for this same behavior without needing to provide the
one option.
collections
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name']);
my $full_names = $results->collections->map(sub { $_->join(' ') });
"collections" returns a Mojo::Collection of Mojo::Collections. Each
inner Mojo::Collection corresponds to one array returned by the
results.
This is similar to "arrays" in Mojo::Pg::Results or "arrays" in
Mojo::mysql::Results, but each arrayref is a Mojo::Collection instead.
flatten
# Mojo::Collection with names of all people who like Pizza
my $results = $db->select(people => ['name'] => {favorite_food => 'Pizza'});
my $names = $results->flatten; # equivalent to $results->arrays->flatten
say 'Pizza lovers:';
say for $names->each;
"flatten" returns a Mojo::Collection with all result arrays flattened
to return a Mojo::Collection with all elements. This is equivalent to
calling "flatten" in Mojo::Collection on the arrays method.
struct
my $struct = $results->struct;
Fetch next row from the statement handle with the result object's array
method, and return it as a struct.
This method is composed from Mojo::DB::Results::Role::Struct.
structs
my $collection = $results->structs;
Fetch all rows from the statement handle with the result object's
arrays method, and return them as a Mojo::Collection object containing
structs.
This method is composed from Mojo::DB::Results::Role::Struct.
TRANSFORM METHODS
"TRANSFORM METHODS" is a group of methods that build on top of
Mojo::Collection::Role::Transform that allow you to transform your
results in meaningful and convenient ways. These are:
* "hashify"
* "hashify_collect"
* "collect_by"
hashify
# access results by a key
my $results = $db->select(people => '*');
my $results_by_name = $results->hashify('name');
# $alice_row is a hash
my $alice_row = $results_by_name->{Alice};
# access by multiple keys with a multilevel hash
my $results_by_full_name = $results->hashify(['first_name', 'last_name']);
# $alice_smith_row is a hash
my $alice_smith_row = $results_by_full_name->{Alice}{Smith};
# store the value as a struct instead of a hash
my $results_by_name = $results->hashify({struct => 1}, 'name');
my $alice_struct = $results_by_name->{Alice};
say 'Alice is ' . $alice_struct->age . ' years old';
"hashify" transforms your results into a hash that stores single rows
or values (usually a column value) behind a key or multiple keys
(usually column values).
"hashify" builds on "hashify" in Mojo::Collection::Role::Transform and
adds useful functionality specific to DB results.
OPTIONS
array
my $results = $db->select(people => '*');
my $results_by_name = $results->hashify({array => 1}, 'name');
my $alice_array = $results_by_name->{Alice};
"array" allows you to store the value as an array instead of the
default "hash". This also means the value provided to the "KEY" "SUB"
or the "VALUE" "SUB", if used, will be an array.
c
my $results = $db->select(people => '*');
my $results_by_name = $results->hashify({c => 1}, 'name');
my $alice_collection = $results_by_name->{Alice};
"c" allows you to store the value as a Mojo::Collection instead of the
default "hash". This also means the value provided to the "KEY" "SUB"
or the "VALUE" "SUB", if used, will be a Mojo::Collection.
hash
my $results = $db->select(people => '*');
my $results_by_name = $results->hashify({hash => 1}, 'name'); # default
my $alice_hash = $results_by_name->{Alice};
"hash" allows you to store the value as a hash. This is the default and
is the same as providing no option hash:
my $results_by_name = $results->hashify('name');
This also means the value provided to the "KEY" "SUB" or the "VALUE"
"SUB", if used, will be a hash.
struct
my $results = $db->select(people => '*');
my $results_by_name = $results->hashify({struct => 1}, 'name');
my $alice_struct = $results_by_name->{Alice};
"struct" allows you to store the value as a readonly struct provided by
Mojo::DB::Results::Role::Struct instead of the default "hash". This
also means the value provided to the "KEY" "SUB" or the "VALUE" "SUB",
if used, will be a readonly struct.
KEY
SINGLE KEY
my $results_by_name = $results->hashify('name');
my $alice_row = $results_by_name->{Alice};
A single key may be used to access values. This key should be the name
of a returned column.
MULTIPLE KEYS
my $results_by_full_name = $results->hashify(['first_name', 'last_name']);
my $alice_smith_row = $results_by_full_name->{Alice}{Smith};
Multiple keys may be used to access values. Multiple keys should be
provided as an arrayref of names of returned columns.
SUB
# single key
my $results_by_name = $results->hashify(sub { $_->{name} });
my $alice_row = $results_by_name->{Alice};
# multiple keys
my $results_by_full_name = $results->hashify(sub { @{ $_ }{qw(first_name last_name)} });
my $alice_smith_row = $results_by_full_name->{Alice}{Smith};
Providing a subroutine for the key allows you to create the key (or
keys) with the returned row. The row is available either as $_ or as
the first argument to the subroutine. The type of the row ("array",
"c", "hash", "struct") that is passed to the subroutine depends on any
"OPTIONS" value that is passed (default is "hash").
If the subroutine returns one key, the hash will be a "SINGLE KEY"
hash. If multiple keys are returned as a list, the hash with be a
"MULTIPLE KEYS" hash.
VALUE
DEFAULT
# values are hashes
my $results_by_name = $results->hashify('name');
my $alice_hash = $results_by_name->{Alice};
# values are still hashes
my $results_by_name = $results->hashify({hash => 1}, 'name');
my $alice_hash = $results_by_name->{Alice};
# values are arrays
my $results_by_name = $results->hashify({array => 1}, 'name');
my $alice_array = $results_by_name->{Alice};
# values are Mojo::Collection's
my $results_by_name = $results->hashify({c => 1}, 'name');
my $alice_collection = $results_by_name->{Alice};
# values are readonly structs
my $results_by_name = $results->hashify({struct => 1}, 'name');
my $alice_struct = $results_by_name->{Alice};
If no value argument is provided, the default is to use the row as the
value according to the type specified in "OPTIONS" ("array", "c",
"hash", "struct"). The default is "hash".
COLUMN
# value will be age
my $results_by_name = $results->hashify('name', 'age');
my $alice_age = $results_by_name->{Alice};
The value can be provided as a column returned in the results and will
be used as the final value in the hash.
SUB
# value will be the age squared
my $results_by_name = $results->hashify('name', sub { $_->{age} * $_->{age} });
my $alice_age_squared = $results_by_name->{Alice};
Providing a subroutine for the value allows you to create the value
with the returned row. The row is available either as $_ or as the
first argument to the subroutine. The type of the row ("array", "c",
"hash", "struct") that is passed to the subroutine depends on any
"OPTIONS" value that is passed (default is "hash").
hashify_collect
# group results by a key in a hash
my $results = $db->select(people => '*');
my $collections_by_name = $results->hashify_collect('name');
# $alice_collection is a Mojo::Collection with all rows with the name Alice as hashes
my $alice_collection = $collections_by_name->{Alice};
# group by multiple keys with a multilevel hash
my $collections_by_full_name = $results->hashify_collect(['first_name', 'last_name']);
# $alice_smith_collection is a Mojo::Collection with all rows with
# the first name Alice and last name Smith as hashes
my $alice_smith_collection = $collections_by_full_name->{Alice}{Smith};
# group the values as structs instead of hashes
my $structs_by_name = $results->hashify_collect({struct => 1}, 'name');
my $alice_structs = $structs_by_name->{Alice};
$alice_structs->each(sub {
say 'Alice is ' . $_->age . ' years old';
});
# collect a single column value
my $ages_by_name = $results->hashify_collect('name', 'age');
# contains all ages in one Mojo::Collection for all rows with the name Alice
my $alice_ages = $ages_by_name->{Alice};
# flatten grouped results
my $results = $db->select(people => '*');
my $column_values_by_name = $results->hashify_collect({flatten => 1}, 'name');
# contains all column values in one Mojo::Collection for all rows with the name Alice
my $alice_all_column_values = $column_values_by_name->{Alice};
"hashify_collect" allows you to group rows behind a key or multiple
keys in a hash.
"hashify_collect" builds on "hashify_collect" in
Mojo::Collection::Role::Transform and adds useful functionality
specific to DB results.
OPTIONS
array
my $results = $db->select(people => '*');
my $collections_by_name = $results->hashify_collect({array => 1}, 'name');
my $alice_collection = $collections_by_name->{Alice};
my $alice_array = $alice_collection->first;
"array" allows you to group rows as arrays instead of the default
"hash". This also means the value provided to the "KEY" "SUB" or the
"VALUE" "SUB", if used, will be an array.
flatten
my $results = $db->select(people => ['name', 'age']);
# trivial example returning arrayref to demonstrate flatten
my $age_collections_by_name = $results->hashify_collect({flatten => 1}, 'name', sub { [$_->{age}] });
my $alice_ages_collection = $age_collections_by_name->{Alice};
my $age_sum = $alice_ages_collection->reduce(sub { $a + $b }, 0);
say "Collective age of Alices is $age_sum years old";
"flatten" flattens all values for a key into the same Mojo::Collection.
"flatten" may be combined with the other type options to specify the
type of the rows that will be passed to the "KEY" "SUB" or the "VALUE"
"SUB".
If no "VALUE" is specified, all returned column values for a row will
be returned in the order they were requested and flattened into the
resulting Mojo::Collection. This works regardless of any type option
that is specified:
my $results = $db->select(people => ['name', 'age']);
# both contain name and age flattened into the collections
my $collections_by_name = $results->hashify_collect({hash => 1, flatten => 1}, sub { $_->{name} });
my $collections_by_name = $results->hashify_collect({struct => 1, flatten => 1}, sub { $_->name });
Any value returned by a "VALUE" "SUB" should be an arrayref or list of
values and all values will be added to the Mojo::Collection:
my $collections_by_name = $results->hashify_collect({flatten => 1}, 'name', sub { $_->{age} }); # flatten not needed in this specific case because it's a list of 1
my $collections_by_name = $results->hashify_collect({flatten => 1}, 'name', sub { [$_->{age}] });
c
my $results = $db->select(people => '*');
my $collections_by_name = $results->hashify_collect({c => 1}, 'name');
my $alice_collections = $collections_by_name->{Alice};
$alice_collections->each(sub {
say 'Random column value is ' . $_->shuffle->first;
});
"c" allows you to group rows as Mojo::Collections instead of the
default "hash". This also means the value provided to the "KEY" "SUB"
or the "VALUE" "SUB", if used, will be a Mojo::Collection.
hash
my $results = $db->select(people => '*');
my $collections_by_name = $results->hashify_collect({hash => 1}, 'name'); # default
my $alice_collection = $collections_by_name->{Alice};
"hash" allows you to group the rows as hashes. This is the default and
is the same as providing no option hash:
my $collections_by_name = $results->hashify_collect('name');
This also means the value provided to the "KEY" "SUB" or the "VALUE"
"SUB", if used, will be a hash.
struct
my $results = $db->select(people => '*');
my $collections_by_name = $results->hashify_collect({struct => 1}, 'name');
my $alice_collection = $collections_by_name->{Alice};
say q{First Alice's age is } . $alice_collection->first->age;
"struct" allows you to group the rows as readonly structs provided by
Mojo::DB::Results::Role::Struct instead of the default "hash". This
also means the value provided to the "KEY" "SUB" or the "VALUE" "SUB",
if used, will be a readonly struct.
KEY
SINGLE KEY
my $collections_by_name = $results->hashify_collect('name');
my $alice_collection = $collections_by_name->{Alice};
A single key may be used to access collections. This key should be the
name of a returned column.
MULTIPLE KEYS
my $collections_by_full_name = $results->hashify_collect(['first_name', 'last_name']);
my $alice_smith_collection = $collections_by_full_name->{Alice}{Smith};
Multiple keys may be used to access collections. Multiple keys should
be provided as an arrayref of names of returned columns.
SUB
# single key
my $collections_by_name = $results->hashify_collect(sub { $_->{name} });
my $alice_collection = $collections_by_name->{Alice};
# multiple keys
my $collections_by_full_name = $results->hashify_collect(sub { @{ $_ }{qw(first_name last_name)} });
my $alice_smith_collection = $collections_by_full_name->{Alice}{Smith};
Providing a subroutine for the key allows you to create the key (or
keys) with the returned row. The row is available either as $_ or as
the first argument to the subroutine. The type of the row ("array",
"c", "hash", "struct") that is passed to the subroutine depends on any
"OPTIONS" value that is passed (default is "hash").
If the subroutine returns one key, the hash will be a "SINGLE KEY"
hash. If multiple keys are returned as a list, the hash with be a
"MULTIPLE KEYS" hash.
VALUE
DEFAULT
# collections contain hashes
my $collections_by_name = $results->hashify_collect('name');
my $alice_collection_of_hashes = $collections_by_name->{Alice};
# collections still contain hashes
my $collections_by_name = $results->hashify_collect({hash => 1}, 'name');
my $alice_collection_of_hashes = $collections_by_name->{Alice};
# collections contain arrays
my $collections_by_name = $results->hashify_collect({array => 1}, 'name');
my $alice_collection_of_arrays = $collections_by_name->{Alice};
# collections contain Mojo::Collection's
my $collections_by_name = $results->hashify_collect({c => 1}, 'name');
my $alice_collection_of_collections = $collections_by_name->{Alice};
# collections contain readonly structs
my $collections_by_name = $results->hashify_collect({struct => 1}, 'name');
my $alice_collection_of_structs = $collections_by_name->{Alice};
If no value argument is provided, the default is to collect the rows as
the value according to the type specified in "OPTIONS" ("array", "c",
"hash", "struct"). The default is "hash".
COLUMN
# age will be collected
my $collections_by_name = $results->hashify_collect('name', 'age');
my $alice_collection_of_ages = $collections_by_name->{Alice};
The value can be provided as a column returned in the results, and this
column value for each row will be collected into the corresponding
Mojo::Collection based on the key(s).
SUB
# collected value will be the age squared
my $collections_by_name = $results->hashify_collect('name', sub { $_->{age} * $_->{age} });
my $alice_collection_of_ages_squared = $collections_by_name->{Alice};
Providing a subroutine for the value allows you to create the collected
values for each returned row. The row is available either as $_ or as
the first argument to the subroutine. The type of the row ("array",
"c", "hash", "struct") that is passed to the subroutine depends on any
"OPTIONS" value that is passed (default is "hash").
You may return a single value, or a list of values to be collected:
my $collections_by_name = $results->hashify_collect('name', sub { $_->{age}, $_->{favorite_food} });
collect_by
# group results by a key in Mojo::Collection's inside of a Mojo::Collection
my $results = $db->select(people => '*');
my $collections_by_name = $results->collect_by('name');
say 'First collection contains rows with name', $collections_by_name->first->first->{name};
# group results by multiple keys
my $collections_by_full_name = $results->collect_by(['first_name', 'last_name']);
my $first_collection = $collections_by_name->first;
say
'First collection contains rows with first name',
$first_collection->first->{first_name},
' and last name ',
$first_collection->first->{last_name};
# group the values as structs instead of hashes
my $structs_by_name = $results->collect_by({struct => 1}, 'name');
$structs_by_name->first->each(sub {
say $_->name, ' is ' . $_->age . ' years old';
});
# collect a single column value
my $ages_by_name = $results->collect_by('name', 'age');
say 'First collection contains ages for name', $ages_by_name->first->first->{name};
# flatten grouped results
my $results = $db->select(people => '*');
# each inner Mojo::Collection is flattened
my $column_values_by_name = $results->collect_by({flatten => 1}, 'name');
"collect_by" allows you to group rows/values that share the same key or
multiple keys in Mojo::Collections inside of a Mojo::Collection.
"collect_by" builds on "collect_by" in
Mojo::Collection::Role::Transform and adds useful functionality
specific to DB results.
OPTIONS
array
my $results = $db->select(people => '*');
my $collections_by_name = $results->collect_by({array => 1}, 'name');
"array" allows you to group rows as arrays instead of the default
"hash". This also means the value provided to the "KEY" "SUB" or the
"VALUE" "SUB", if used, will be an array.
flatten
my $results = $db->select(people => ['name', 'age']);
# trivial example returning arrayref to demonstrate flatten
my $age_collections_by_name = $results->collect_by({flatten => 1}, 'name', sub { [$_->{age}] });
"flatten" flattens all values for each inner Mojo::Collection.
"flatten" may be combined with the other type options to specify the
type of the rows that will be passed to the "KEY" "SUB" or the "VALUE"
"SUB".
If no "VALUE" is specified, all returned column values for a row will
be returned in the order they were requested and flattened into the
resulting Mojo::Collection. This works regardless of any type option
that is specified:
my $results = $db->select(people => ['name', 'age']);
# both contain name and age flattened into the inner collections
my $collections_by_name = $results->collect_by({hash => 1, flatten => 1}, sub { $_->{name} });
my $collections_by_name = $results->collect_by({struct => 1, flatten => 1}, sub { $_->name });
Any value returned by a "VALUE" "SUB" should be an arrayref or list of
values and all values will be added to the inner Mojo::Collections:
my $collections_by_name = $results->collect_by({flatten => 1}, 'name', sub { $_->{age} }); # flatten not needed in this specific case because it's a list of 1
my $collections_by_name = $results->collect_by({flatten => 1}, 'name', sub { [$_->{age}] });
c
my $results = $db->select(people => '*');
my $collections_by_name = $results->collect_by({c => 1}, 'name');
$collections_by_name->first->first->each(sub {
say 'Random column value is ' . $_->shuffle->first;
});
"c" allows you to group rows as Mojo::Collections instead of the
default "hash". This also means the value provided to the "KEY" "SUB"
or the "VALUE" "SUB", if used, will be a Mojo::Collection.
hash
my $results = $db->select(people => '*');
my $collections_by_name = $results->collect_by({hash => 1}, 'name'); # default
"hash" allows you to group the rows as hashes. This is the default and
is the same as providing no option hash:
my $collections_by_name = $results->collect_by('name');
This also means the value provided to the "KEY" "SUB" or the "VALUE"
"SUB", if used, will be a hash.
struct
my $results = $db->select(people => '*');
my $collections_by_name = $results->collect_by({struct => 1}, 'name');
my $first_collection = $collections_by_name->first;
say $first_collection->first->name, ' is ', $first_collection->first->age, ' years old';
"struct" allows you to group the rows as readonly structs provided by
Mojo::DB::Results::Role::Struct instead of the default "hash". This
also means the value provided to the "KEY" "SUB" or the "VALUE" "SUB",
if used, will be a readonly struct.
KEY
SINGLE KEY
my $collections_by_name = $results->collect_by('name');
A single key may be used to group rows/values into inner
Mojo::Collections. This key should be the name of a returned column.
MULTIPLE KEYS
my $collections_by_full_name = $results->collect_by(['first_name', 'last_name']);
Multiple keys may be used to group rows/values into inner
Mojo::Collections. Multiple keys should be provided as an arrayref of
names of returned columns.
SUB
# single key
my $collections_by_name = $results->collect_by(sub { $_->{name} });
# multiple keys
my $collections_by_full_name = $results->collect_by(sub { @{ $_ }{qw(first_name last_name)} });
Providing a subroutine for the key allows you to create the key (or
keys) with the returned row. The row is available either as $_ or as
the first argument to the subroutine. The type of the row ("array",
"c", "hash", "struct") that is passed to the subroutine depends on any
"OPTIONS" value that is passed (default is "hash").
If the subroutine returns one key, the hash will be a "SINGLE KEY"
hash. If multiple keys are returned as a list, the hash with be a
"MULTIPLE KEYS" hash.
VALUE
DEFAULT
# collections contain hashes
my $collections_by_name = $results->collect_by('name');
# collections still contain hashes
my $collections_by_name = $results->collect_by({hash => 1}, 'name');
# collections contain arrays
my $collections_by_name = $results->collect_by({array => 1}, 'name');
# collections contain Mojo::Collection's
my $collections_by_name = $results->collect_by({c => 1}, 'name');
# collections contain readonly structs
my $collections_by_name = $results->collect_by({struct => 1}, 'name');
If no value argument is provided, the default is to collect the rows as
the value according to the type specified in "OPTIONS" ("array", "c",
"hash", "struct"). The default is "hash".
COLUMN
# age will be collected
my $collections_by_name = $results->collect_by('name', 'age');
The value can be provided as a column returned in the results, and this
column value for each row will be collected into the corresponding
inner Mojo::Collection based on the key(s).
SUB
# collected value will be the age squared
my $collections_by_name = $results->collect_by('name', sub { $_->{age} * $_->{age} });
Providing a subroutine for the value allows you to create the collected
values for each returned row. The row is available either as $_ or as
the first argument to the subroutine. The type of the row ("array",
"c", "hash", "struct") that is passed to the subroutine depends on any
"OPTIONS" value that is passed (default is "hash").
You may return a single value, or a list of values to be collected:
my $collections_by_name = $results->collect_by('name', sub { $_->{age}, $_->{favorite_food} });
DIE METHODS
"DIE METHODS" are equivalent to the "get", "get_by_name", "c", and
"c_by_name" methods above, however, the die option for these methods is
passed as true for you and the method will die if there is no next row
to be retrieved.
Additionally, "struct_or_die", "array_or_die", and "hash_or_die" are
provided.
get_or_die
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
# all of these die if there is no next row to be retrieved
# return the first column
my $name = $results->get_or_die;
# same as above but specifying index
my $name = $results->get_or_die(0);
# negative indexes may be used
my $name = $results->get_or_die(-3);
# any column may be gotten with an index
my $age = $results->get_or_die(1);
Same as "get", but dies if there is no next row to be retrieved.
get_by_name_or_die
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
# dies if there is no next row to be retrieved
my $name = $results->get_by_name_or_die('name');
Same as "get_by_name", but dies if there is no next row to be
retrieved.
c_or_die
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name']);
# dies if there is no next row to be retrieved
my $full_name = $results->c_or_die->join(' ');
Same as "c", but dies if there is no next row to be retrieved.
c_by_name_or_die
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name']);
# dies if there is no next row to be retrieved
my $full_name = $results->c_by_name_or_die('first_name', 'middle_name', 'last_name')->join(' ');
Same as "c_by_name", but dies if there is no next row to be retrieved.
struct_or_die
my $results = $db->select(people => '*' => {id => 123});
# dies if there is no next row to be retrieved
my $person_struct = $results->struct_or_die;
"struct_or_die" is the same as "struct", but dies if there is no next
row to be retrieved.
array_or_die
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name'] => {id => 123});
# dies if there is no next row to be retrieved
my $full_name = join ' ', @{ $results->array_or_die };
"array_or_die" is similar to "array" in Mojo::Pg::Results or "array" in
Mojo::mysql::Results, but dies if there is no next row to be retrieved.
hash_or_die
my $results = $db->select(people => '*' => {id => 123});
# dies if there is no next row to be retrieved
my $person = $results->hash_or_die;
"hash_or_die" is similar to "hash" in Mojo::Pg::Results or "hash" in
Mojo::mysql::Results, but dies if there is no next row to be retrieved.
ONE METHODS
"ONE METHODS" are equivalent to the "get", "get_by_name", "c",
"c_by_name", and "struct" methods above, however, the one option for
these methods is passed as true for you and the method will die unless
exactly one row was returned.
Additionally, "one_struct", "one_array" and "one_hash" are provided.
one
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
# all of these die unless exactly one row was returned
# return the first column
my $name = $results->one;
# same as above but specifying index
my $name = $results->one(0);
# negative indexes may be used
my $name = $results->one(-3);
# any column may be gotten with an index
my $age = $results->one(1);
Same as "get", but dies unless exactly one row was returned.
one_by_name
my $results = $db->select(people => ['name', 'age', 'favorite_food'] => {id => 123});
# dies unless exactly one row was returned
my $name = $results->one_by_name('name');
Same as "get_by_name", but dies unless exactly one row was returned.
one_c
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name'] => {id => 123});
# dies unless exactly one row was returned
my $full_name = $results->one_c->join(' ');
Same as "c", but dies unless exactly one row was returned.
one_c_by_name
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name'] => {id => 123});
# dies unless exactly one row was returned
my $full_name = $results->one_c_by_name('first_name', 'middle_name', 'last_name')->join(' ');
Same as "c_by_name", but dies unless exactly one row was returned
one_struct
my $results = $db->select(people => '*' => {id => 123});
# dies unless exactly one row was returned
my $person_struct = $results->one_struct;
"one_struct" is the same as "struct", but dies unless exactly one row
was returned.
one_array
my $results = $db->select(people => ['first_name', 'middle_name', 'last_name'] => {id => 123});
# dies unless exactly one row was returned
my $full_name = join ' ', @{ $results->one_array };
"one_array" is similar to "array" in Mojo::Pg::Results or "array" in
Mojo::mysql::Results, but dies unless exactly one row was returned.
one_hash
my $results = $db->select(people => '*' => {id => 123});
# dies unless exactly one row was returned
my $person = $results->one_hash;
"one_hash" is similar to "hash" in Mojo::Pg::Results or "hash" in
Mojo::mysql::Results, but dies unless exactly one row was returned.
AUTHOR
Adam Hopkins <
[email protected]>
COPYRIGHT
Copyright 2019- Adam Hopkins
LICENSE
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
SEE ALSO
* Mojo::Pg::Results
* Mojo::mysql::Results
* Mojo::DB::Role::ResultsRoles
* Mojo::DB::Results::Role::Struct
* Role::Tiny
* Mojo::Base