Нет такого отношения для сгруппированного запроса DBIC - PullRequest
0 голосов
/ 25 февраля 2019

Я пытался подсчитать все продукты, сгруппированные по их типам, используя этот запрос SQL:

  select pt.id,
         pt.name,
         count(p.id) as n
    from prd.product_types as pt,
         prd.products as p
   where pt.id = p.type
group by pt.id,
         pt.name
order by pt.name

Эти две таблицы ( prd.product_types и prd.products ) отображаются этими двумя классами DBIC:

package ki::Schema::Result::ProductTypes;

use strict;
use warnings;
use utf8;
use Moose;
use MooseX::NonMoose;
use MooseX::MarkAsMethods autoclean => 1;

extends 'DBIx::Class::Core';

__PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp", "EncodedColumn");
__PACKAGE__->table("prd.product_types");
__PACKAGE__->add_columns(
  "id",
  {
    data_type => "uuid",
    default_value => \"uuid_generate_v4()",
    is_nullable => 0,
    size => 16,
  },
  "name",
  { data_type => "varchar", is_nullable => 0, size => 128 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("uk_product_types", ["name"]);
__PACKAGE__->has_many(
  "products",
  "ki::Schema::Result::Products",
  { "foreign.type" => "self.id" },
  { cascade_copy => 0, cascade_delete => 0 },
);
__PACKAGE__->meta->make_immutable;

1;

и

package ki::Schema::Result::Products;

use strict;
use warnings;
use utf8;
use Moose;
use MooseX::NonMoose;
use MooseX::MarkAsMethods autoclean => 1;

extends 'DBIx::Class::Core';

__PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp", "EncodedColumn");
__PACKAGE__->table("prd.products");
__PACKAGE__->add_columns(
  "id",
  {
    data_type => "uuid",
    default_value => \"uuid_generate_v4()",
    is_nullable => 0,
    size => 16,
  },
  "type",
  { data_type => "uuid", is_foreign_key => 1, is_nullable => 0, size  => 16 },
  "name",
  { data_type => "varchar", is_nullable => 0, size => 128 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("uk_products", ["name"]);
__PACKAGE__->belongs_to(
  "type",
  "ki::Schema::Result::ProductTypes",
  { id => "type" },
  { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
__PACKAGE__->meta->make_immutable;

1;

Когда я устанавливаю соединение в своем контроллере Catalyst, я получаю «Нет таких отношений»:

DBIx::Class::ResultSource::_resolve_join(): No such relationship prd.products on ProductTypes

Результирующий набор таков:

$c->stash(product_types_rs => $c->model('DB_T::ProductTypes'));

, и объединение выглядит так:

    $c->stash(categories => [$c->stash->{product_types_rs}->search({}, {
        join     => [qw/ prd.products /],
        select   => [ { count => 'prd.products.id' } ],
        as       => [qw/ n /],
        group_by => [qw/ id /],
        order_by => 'name ASC'
    })]);

Приведенный выше запрос представляет собой однозначное воспроизведениезапрос Artist-CD из документации DBIC.Но есть кое-что, чего я не могу понять, и это неправильно.

Вернемся с некоторыми новостями:

единственный способ, который работал до сих пор, это:

$c->stash(categories => [$c->stash->{product_types_rs}->search({}, 
{
    '+select' => [{ COUNT => 'products.id', -as => 'n'}],
    join => ['products'],
    group_by => 'me.id',
    order_by => { -desc => ' COUNT( products.id )' },
})])

и его SQL выглядит следующим образом:

  SELECT me.id, me.name, COUNT( products.id ) AS n
    FROM prd.product_types me LEFT JOIN prd.products products 
                                     ON products.type = me.id
GROUP BY me.id
ORDER BY COUNT( products.id ) DESC

Я протестировал сгенерированный запрос SQL и получил желаемый результат.Есть остающаяся проблема.На мой взгляд, я использую этот цикл

[% FOREACH category IN categories -%]
    <li>([% category.n %])</li>
[% END -%]

для итерации набора результатов.Но значение n не отображается, даже если Dumper-> Dump () отображает правильные данные:

...
'_column_data' => {
    'name' => "XTorckAlsa",
    'n' => 1,
    'id' => '88b94b12-4169-4964-9022-3eebbc5c05c5'
},
...
'_column_data' => {
    'name' => "Pledicts11",
    'n' => 5,
    'id' => 'ebda7223-99e3-48d6-b662-c7d17d124787'
},

Я все еще что-то упускаю.

1 Ответ

0 голосов
/ 26 февраля 2019

Вы назвали отношение products, так что это то, что вам нужно использовать в параметре join.Имя таблицы никогда не используется ни в одном параметре DBIC, только в определении ResultSource.

В одном из параметров никогда не должно быть больше одной точки.

Рекомендуется использовать columns вместо select и as, поскольку он менее подвержен ошибкам пользователя.

order_by также поддерживает не-литеральный синтаксис SQL, который

[{ -asc => 'columnname' }]
...