NAME
AmberDB::Index::Facet - Column-oriented facet indexing, disjunctive counting, and navigation menu generator
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,
});
DESCRIPTION
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.
Inheritance Note: AmberDB inherits from AmberDB::Index::Facet via use parent. All facet query and menu methods documented below are invoked directly on $adb.
KEY ARCHITECTURAL FEATURES
1. Columnar Per-Block Storage (
_${blk}.fac): Facet data is stored in partitioned columnar forward index files (${table_path}_${blk}.fac). Each file maps Record ID to packed value IDs, enabling fast single-column scans.2. Active-Only Storage Guarantee: Facet index files store only currently active records. Inactive, discontinued, or out-of-stock records violating
facet_rules/junk_rulesare excluded during indexing, eliminating the overhead of scanning historical records.3. Bidirectional String Dictionary (
_${blk}.str): Text facets (e.g. colors, specifications) map transparently between string labels and compact numeric dictionary IDs.4. Dynamic Scoping (
base_ids): When computing facet counts within search results or subcategories, passingbase_ids => \@idsbounds the aggregation strictly to matching records.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.
METHODS
facet_menu($tableid, \%selected, \@facet_defs, [\%options])
High-level faceted navigation menu generator. =over 4 =item * $tableid: Table name (e.g. catalog_product). =item * \%selected: Hash of currently active filter selections: { block_idx => $val_or_arr_ref }. =item * \@facet_defs: Array of facet block definitions (or reads directly from table schema facet_block if omitted). =item * \%options: Optional parameters: - base_ids: Array reference of record IDs to scope calculation (e.g. search result IDs). - sort: 'count' (default, descending count) or 'label' / 'name' (alphabetical). - top: Limit maximum items returned per facet group (e.g. 10). - min_count: Minimum count required to include an item (default: 1). =back
Returns a comprehensive result hash: { count => $total, ids => \@filtered_ids, groups => \@groups, active_counts => \%counts }.
my $menu = $adb->facet_menu("catalog_product", \%selected, \@facet_defs);
field_fltkeys($tableid, \%opts)
Calculates facet key counts for a target block directly from active _${target_block}.fac. Automatically resolves dictionary string labels.
my $counts = $adb->field_fltkeys("catalog_product", { target_block => 2, base_ids => \@scoped_ids });
field_allfltkeys($tableid, \@blk_list, \@base_scope)
Calculates facet key counts across multiple active block files in a single pass.
facet_rules($table_info, @record)
Evaluates whether a record qualifies for inclusion in facet index files. Automatically integrates with junk_rules.
AUTHOR
Maruf Cetin <marufcetin@gmail.com>
LICENSE AND COPYRIGHT
Copyright (C) 2020-2026 Maruf Cetin.
This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.