递归地膨胀列

时间:2018-04-15 18:16:22

标签: perl dbix-class

我在3个表User,Role和Project之间有很多关系。 这导致映射表User_has_Roles_has_Projects 现在,在我的代码中,我可以通过编写来到映射表 @a=$s->resultset('User')->find({idUser=>1})->user_has_roles_has_projects->all

我想得到的东西相当于映射表与其他3个表的左连接。 即。

idUser|name
1     |Vijay

idRole|role
1     | Manager
2     | Developer

idProject |prj|path
1         |foo | /prj/foo
2         | bar| /prj/bar

和映射表为

idUser|idRole|idProject
1     | 2    | 2

查询应该给我

idUser|idRole|idProject|name|role|prj|path
1     | 2    | 2       | Vijay|Developer|bar|/prj/bar

我想将上述内容作为简单的AOH或AOA。 我可以得到的最接近的是通过在映射表的每一行上调用get_inflate_columns,然后再次对结果的每个值调用get_inflate_columns。最后以所需的格式合并结果。 即类似于

的东西
   foreach my $idx (@a){
    my %b=$a[0]->get_inflated_columns
        foreach my $val (keys %b){
       @val= $b{$val}->get_columns 
       $b{$val}=\@val

    }
  push @result,\%b 
}
 # Post process @result to get a simple AOA or AOH

有没有更好的方法来达到上述效果?

1 个答案:

答案 0 :(得分:1)

使用DBIx::Class::Helper::Row::ToJSON。调用TO_JSON会为您提供结果类对象的hashref,它可以递归地整齐地串行化。请参阅下面评论中的输出。

use DBIx::Class::Schema::Loader qw();
require DBIx::Class::Helper::Row::ToJSON;
use JSON::MaybeXS qw();

DBIx::Class::Schema::Loader->loader_options(
    naming => undef,
    preserve_case => 1,
    moniker_map => sub { shift->name },
    col_accessor_map => sub { shift->name },
    rel_name_map => sub {
        my $t = shift;
        $t->{type} eq 'belongs_to'
            ? $t->{local_columns}[0]
            : $t->{remote_moniker}
    },
);
my $schema = DBIx::Class::Schema::Loader->connect(
    'DBI:Pg:', (undef) x 2, {quote_names => 1}
);
for my $sourcename ($schema->sources) {
    my $src = $schema->source($sourcename);
    $src->result_class->load_components('Helper::Row::ToJSON');
    for my $colname ($src->columns) {
        $src->{_columns}{$colname}{is_serializable} = 1
            if 'text' eq $src->column_info($colname)->{data_type};
    }
};

# hashref of resultclass objects
my $h = $schema->resultset('users')->find({idUser=>1})->user_has_roles_has_projects->first->TO_JSON;
# {
#     idProject => DBIx::Class::Schema::Loader::Result::projects  {
#         internals: {
#             _column_data     {
#                 idProject   2,
#                 path        "/prj/bar",
#                 prj         "bar"
#             },
#             _in_storage      1,
#             _result_source   DBIx::Class::ResultSource::Table
#         }
#     },
#     idRole => DBIx::Class::Schema::Loader::Result::roles  {
#         internals: {
#             _column_data     {
#                 idRole   2,
#                 role     "Developer"
#             },
#             _in_storage      1,
#             _result_source   DBIx::Class::ResultSource::Table
#         }
#     },
#     idUser => DBIx::Class::Schema::Loader::Result::users  {
#         internals: {
#             _column_data     {
#                 idUser   1,
#                 name     "Vijay"
#             },
#             _in_storage      1,
#             _result_source   DBIx::Class::ResultSource::Table
#         }
#     }
# }

print JSON::MaybeXS->new(convert_blessed => 1, pretty => 1)->encode($h);

# {
#     "idUser" : {
#         "name" : "Vijay",
#         "idUser" : 1
#     },
#     "idProject" : {
#         "idProject" : 2,
#         "path" : "/prj/bar",
#         "prj" : "bar"
#     },
#     "idRole" : {
#         "role" : "Developer",
#         "idRole" : 2
#     }
# }

__END__
create table "users" (
    "idUser" bigint primary key,
    "name" text not null
);
insert into "users" ("idUser", "name") values (1, 'Vijay');
create type "e_role" as enum ('Manager', 'Developer');
create table "roles" (
    "idRole" int primary key,
    "role" e_role null
);
insert into "roles" ("idRole", "role") values (1, 'Manager');
insert into "roles" ("idRole", "role") values (2, 'Developer');
create table "projects" (
    "idProject" int primary key,
    "prj" text not null,
    "path" text not null
);
insert into "projects" ("idProject", "prj", "path") values (1, 'foo', '/prj/foo');
insert into "projects" ("idProject", "prj", "path") values (2, 'bar', '/prj/bar');
create table "user_has_roles_has_projects" (
    "idUser" int references "users" ("idUser"),
    "idRole" int references "roles" ("idRole"),
    "idProject" int references "projects" ("idProject")
);
insert into "user_has_roles_has_projects" ("idUser", "idRole", "idProject") values (1, 2, 2);