AmberDB
view release on metacpan or search on metacpan
lib/AmberDB/Index/Facet.pm view on Meta::CPAN
);
$filtered_ids = $f_res->{ids} || [];
if ( $base_scope && @$base_scope ) {
my %scope_map = map { $_ => 1 } @$base_scope;
$filtered_ids = [ grep { $scope_map{$_} } @$filtered_ids ];
}
$total_count = scalar @$filtered_ids;
}
elsif ( $base_scope && @$base_scope ) {
$total_count = scalar @$base_scope;
if ($limit) {
( undef, $filtered_ids ) = $self->recs_cutting( $start, $limit, @$base_scope );
}
else {
$filtered_ids = $base_scope;
}
}
else {
my $fac_path = "$table_path.fac";
if ( -e $fac_path ) {
( undef, my @all_active ) = $self->index_get( $fac_path, "active" );
unless (@all_active) {
my $inx_path = "$table_path.inx";
( undef, @all_active ) = $self->index_get( $inx_path, "keys" ) if -e $inx_path;
}
$total_count = scalar @all_active;
if ($limit) {
( undef, $filtered_ids ) = $self->recs_cutting( $start, $limit, @all_active );
}
else {
$filtered_ids = \@all_active;
}
}
}
# 2. Compute Facet Counts (Disjunctive / Multi-pass)
my %all_counts;
if ( !%active_filter ) {
my @blks = map { ref($_) eq 'HASH' ? $_->{blk} : $_ } @$facet_defs;
my $raw_counts = $self->field_allfltkeys( $tableid, \@blks, $base_scope );
%all_counts = %{ $raw_counts || {} };
}
else {
for my $cfg (@$facet_defs) {
my $blk = ref($cfg) eq 'HASH' ? $cfg->{blk} : $cfg;
my %excl = %active_filter;
delete $excl{$blk};
my $cnt_map = $self->field_fltkeys(
$tableid,
{
target_block => $blk,
filter => \%excl,
base_ids => $base_scope,
}
);
$all_counts{$blk} = $cnt_map || {};
}
}
# 3. Build Menu Groups, Whitelist & Batch Label Resolution (.unq / RDBM)
my @groups;
my %groups_by_blk;
my %active_counts;
for my $cfg (@$facet_defs) {
my $blk = ref($cfg) eq 'HASH' ? $cfg->{blk} : $cfg;
my $label = ref($cfg) eq 'HASH' ? ( $cfg->{label} // "Grup $blk" ) : "Grup $blk";
my $counts = $all_counts{$blk} // {};
next unless %$counts || ( ref($cfg) eq 'HASH' && $cfg->{required} );
my @vals = keys %$counts;
# Whitelist: filter_block
if ( ref($cfg) eq 'HASH' && $cfg->{filter_block} ) {
my @fb = @{ $cfg->{filter_block} };
my ( $fb_blk, $fb_op, $fb_val ) = @fb == 3 ? @fb : ( $fb[0], 'eq', $fb[1] );
my $all_map = $self->field_keyvals( $cfg->{table}, $fb_blk );
my %allowed;
for my $k ( keys %$all_map ) {
if ( $self->_cmp_op( $k, $fb_op, $fb_val ) ) {
$allowed{$_} = 1 for @{ $all_map->{$k} };
}
}
@vals = grep { $allowed{$_} } @vals;
}
# filter_op on value
if ( ref($cfg) eq 'HASH' && $cfg->{filter_op} ) {
my ( $fo_op, $fo_val ) = @{ $cfg->{filter_op} };
@vals = grep { $self->_cmp_op( $_, $fo_op, $fo_val ) } @vals;
}
# csv_list whitelist if defined
if ( ref($cfg) eq 'HASH' && defined $cfg->{csv_list} && $cfg->{csv_list} ne '' ) {
my %csv_allowed = map { $_ => 1 } split /,/, $cfg->{csv_list};
@vals = grep { $csv_allowed{$_} } @vals;
}
# Sorting
my $sort_mode = ( ref($cfg) eq 'HASH' ? $cfg->{sort} : '' ) || 'count';
if ( $sort_mode eq 'count' ) {
@vals = sort { ( $counts->{$b} || 0 ) <=> ( $counts->{$a} || 0 ) } @vals;
}
elsif ( $sort_mode eq 'value' ) {
@vals = sort { $a cmp $b } @vals;
}
# Top-N Limiting
my $limit_n = ( ref($cfg) eq 'HASH' ? ( $cfg->{limit} // $cfg->{display_limit} ) : 0 ) || 0;
if ( $limit_n && @vals > $limit_n ) {
@vals = @vals[ 0 .. ( $limit_n - 1 ) ];
}
# Batch Label Resolution (RDBM -> .unq bidirectional -> option)
my %name_map;
if ( ref($cfg) eq 'HASH' && $cfg->{table} ) {
if (@vals) {
my @recs = $self->read_list( $cfg->{table}, \@vals );
my $name_idx = $cfg->{name_idx} // 2;
( run in 1.407 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )