AmberDB
view release on metacpan or search on metacpan
lib/AmberDB/Base/Facet.pm view on Meta::CPAN
for my $val (@vals) {
my $text = $res->{"$blk:n:$val"};
if ( defined $text && $text ne '' ) {
$name_map{$val} = $text;
}
}
}
}
# Åema option alanı fallback'i (örn: "1:SatıÅta,0:SatıŠDıÅı")
my $opt_str = $table_info->{blocks}->[$blk]->{option} // '';
if ($opt_str) {
for my $pair ( split /,/, $opt_str ) {
my ( $v, $l ) = split /:/, $pair, 2;
$name_map{$v} //= $l // $v;
}
}
}
# Active status for this block
my %selected_vals = map { $_ => 1 } @{ $active_filter{$blk} // [] };
my $active_cnt = scalar keys %selected_vals;
$active_counts{$blk} = $active_cnt;
my @items;
for my $val (@vals) {
push @items, {
uid => "fc_${blk}_${val}",
param => "f$blk",
val => $val,
label => ( $name_map{$val} // $val ),
count => ( $counts->{$val} // 0 ),
checked => ( $selected_vals{$val} ? "1" : "" ),
};
}
my $group_data = {
blk => $blk,
name => $label,
active => ( $active_cnt ? "1" : "" ),
active_count => $active_cnt,
records => \@items,
};
push @groups, $group_data;
$groups_by_blk{$blk} = \@items;
}
my $res = {
count => $total_count,
ids => $filtered_ids,
groups => \@groups,
groups_by_blk => \%groups_by_blk,
active_counts => \%active_counts,
counts => \%all_counts,
};
return wantarray ? @groups : $res;
}
=encoding utf8
=head1 NAME
AmberDB::Index::Facet - Column-oriented facet indexing, disjunctive counting, and navigation menu generator
=head1 SYNOPSIS
# Querying from AmberDB instance ($adb inherits AmberDB::Index::Facet):
# 1. Generate full-catalog or filtered facet menu with disjunctive counts:
my $menu_data = $adb->facet_menu(
"catalog_product",
{ 1 => "5", 2 => [ "12", "14" ] }, # %selected_filters
\@facet_block_definitions,
{ sort => 'count', top => 10 } # %options
);
# 2. Dynamic Scoped facet menu (e.g. within search results or category scope):
my $search_facets = $adb->facet_menu(
"catalog_product",
\%selected,
\@facet_defs,
{ base_ids => \@search_result_ids }
);
# 3. Direct facet key counts for a single block:
my $counts = $adb->field_fltkeys("catalog_product", {
target_block => 2,
base_ids => \@active_product_ids,
});
=head1 DESCRIPTION
C<AmberDB::Index::Facet> provides a high-performance, column-oriented forward indexing and disjunctive facet aggregation engine designed for low-latency faceted navigation across large-scale catalogs.
B<Inheritance Note:> C<AmberDB> inherits from C<AmberDB::Index::Facet> via C<use parent>. All facet query and menu methods documented below are invoked directly on C<$adb>.
=head1 KEY ARCHITECTURAL FEATURES
=over 4
=item * B<1. Columnar Unified Storage (C<$table_path.fac>):> Facet data is stored in a unified columnar forward index file (C<$table_path.fac>). Each record's block values are keyed as C<$blk:$rid> mapping to packed value IDs, enabling fast single-co...
=item * B<2. Active-Only Storage Guarantee:> Facet index files store B<only currently active records>. Inactive, discontinued, or out-of-stock records violating C<facet_rules> / C<junk_rules> are excluded during indexing, eliminating the overhead of ...
=item * B<3. Bidirectional String Dictionary (C<.unq>):> Text facets (e.g. colors, specifications) map transparently between string labels and compact numeric dictionary IDs.
=item * B<4. Dynamic Scoping (C<base_ids>):> When computing facet counts within search results or subcategories, passing C<base_ids =E<gt> \@ids> bounds the aggregation strictly to matching records.
=item * B<5. Multi-Select Disjunctive Faceting:> Supports multi-selection where checking multiple items within the same filter group uses OR logic (showing counts of remaining options), while combining across different filter groups uses AND logic.
=back
=head1 METHODS
=head2 facet_menu($tableid, [\%options])
High-level faceted navigation menu generator.
Options:
( run in 0.627 second using v1.01-cache-2.11-cpan-364913b4093 )