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 <srchulo@cpan.org>

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