Facets
Build faceted navigation with Sigmie — term, price histogram, and stats facets, with disjunctive and conjunctive logic for e-commerce sidebars.
On this page
Facets are the aggregated counts that drive filter sidebars: “Brand: Apple (12), Dell (8)” or “Price: $0–$100 (124), $100–$500 (89)”. Sigmie generates them automatically from your property definitions — define a category('brand'), request facets('brand'), and you get back the counts.
use Sigmie\Mappings\NewProperties; $props = new NewProperties;$props->category('brand');$props->price(); $response = $sigmie->newSearch('products') ->properties($props) ->queryString('laptop') ->facets('brand price:100') ->get(); $facets = $response->json('facets');// ['brand' => ['Apple' => 5, 'Dell' => 3], 'price' => [...]]
Term facets
Category and keyword fields produce term counts:
$props = new NewProperties;$props->category('brand');$props->keyword('color'); $response = $sigmie->newSearch('products') ->properties($props) ->queryString('shoes') ->facets('brand color') ->get(); $response->json('facets');// ['brand' => ['Nike' => 15, 'Adidas' => 12], 'color' => ['black' => 10, ...]]
Use category() for categorical data (brand, department, genre). Use keyword() for exact-match strings (SKU, status).
Price facets
Price fields return min, max, and a histogram. The argument after : is the bucket size:
$props->price(); $response = $sigmie->newSearch('products') ->properties($props) ->queryString('laptop') ->facets('price:100') // $100 buckets ->get(); $price = $props->get()['price']->facets($response->facetAggregations());// [// 'min' => 299,// 'max' => 1499,// 'histogram' => [// 200 => 3, // 3 in $200–$299// 300 => 8,// 400 => 5,// ...// ],// ]
Pick interval size to match your data range — $10 for cheap items, $100 for big-ticket.
Number facets
Number fields return statistics:
$props->number('rating'); $response = $sigmie->newSearch('products') ->properties($props) ->queryString('laptop') ->facets('rating') ->get(); $stats = $props->get()['rating']->facets($response->facetAggregations());// [// 'count' => 127,// 'min' => 1.0,// 'max' => 5.0,// 'avg' => 4.3,// 'sum' => 546.1,// ]
Text facets
Text fields need a .keyword sub-field for faceting:
$props->text('author')->keyword(); $response = $sigmie->newSearch('articles') ->properties($props) ->queryString('technology') ->facets('author') ->get();
Filtering with facets
Global filters
filters() applies to both results and facet counts:
$sigmie->newSearch('products') ->properties($props) ->queryString('laptop') ->filters("brand:'Apple' AND price:500..1500") ->facets('brand category price:100') ->get();
Facet-specific filters
Pass a filter string as the second argument to facets():
$sigmie->newSearch('products') ->properties($props) ->queryString('laptop') ->facets('brand category color', "brand:'Apple' AND category:'electronics'") ->get();
Disjunctive vs conjunctive
E-commerce facets usually want disjunctive logic: selecting two brands should show items from either brand, and both brand options should remain visible in the sidebar.
Disjunctive (OR within a field)
$props->category('color')->facetDisjunctive();$props->category('size')->facetDisjunctive(); $sigmie->newSearch('products') ->properties($props) ->queryString('shirt') ->facets('color size', "color:'red' color:'blue' size:'lg'") ->get();
- Multiple values for the same field combine with OR:
color:red OR color:blue. - Different fields combine with AND:
(color) AND (size). - Both red and blue stay visible in color facets.
Conjunctive (AND within a field)
$props->category('color')->facetConjunctive();$props->category('material')->facetConjunctive();
Multiple values combine with AND: only items matching every selected value are returned. Use this when filters narrow a set of multi-valued documents (a product with multiple tags).
Self-exclusion
With disjunctive facets, a field’s own filter doesn’t affect that field’s facet counts — so selecting “Apple” still shows you how many Dell, HP, Lenovo items exist:
$sigmie->newSearch('products') ->properties($props) ->filters("stock>0") ->facets('color size', "color:'green'") ->get();
- Color facets show every color available (not just green).
- Size facets reflect sizes available for green items.
- Results contain only green items.
This is the standard pattern for filter UIs.
Nested fields
Use dot notation:
$props->nested('attributes', function (NewProperties $p) { $p->keyword('color'); $p->price();}); $response = $sigmie->newSearch('products') ->properties($props) ->queryString('shirt') ->facets('attributes.color attributes.price:50') ->get(); $compiled = $props->get();$colors = $compiled->get('attributes.color')->facets($response->facetAggregations());
Multi-level nesting works too:
$props->nested('product', function (NewProperties $p) { $p->nested('variants', function (NewProperties $p) { $p->keyword('size'); $p->price(); });}); ->facets('product.variants.size product.variants.price:25')
Reading facet data
From the response JSON
$allFacets = $response->json('facets');$brand = $response->json('facets.brand');$color = $response->json('facets.color');
Through property objects
For price and number facets, the property object computes structured data:
$compiled = $props->get(); $price = $compiled['price']->facets($response->facetAggregations());$min = $price['min'];$max = $price['max'];$histogram = $price['histogram']; $rating = $compiled['rating']->facets($response->facetAggregations());$avg = $rating['avg'];$count = $rating['count'];
Combined example
A realistic e-commerce facet setup:
$props = new NewProperties;$props->category('category')->facetDisjunctive();$props->category('brand')->facetDisjunctive();$props->category('color')->facetDisjunctive();$props->category('size')->facetDisjunctive();$props->price();$props->number('rating');$props->number('stock'); $response = $sigmie->newSearch('products') ->properties($props) ->queryString($searchTerm) ->filters("stock>0") ->facets( 'category brand color size price:50 rating', "category:'electronics' brand:'apple' price:500..1500" ) ->get(); $compiled = $props->get();$brand = $response->json('facets.brand');$color = $response->json('facets.color');$price = $compiled['price']->facets($response->facetAggregations());$rating = $compiled['rating']->facets($response->facetAggregations());
Empty search with facets
Browsing without a query string:
$response = $sigmie->newSearch('products') ->properties($props) ->queryString('') ->facets('category brand price:100') ->get();
Returns facets across the entire dataset.
See also
- Aggregations — raw
terms,range,histogram,statsaggregations. - Filter Parser — the syntax used in
filters()andfacets(). - Mappings & Properties —
facetDisjunctive()/facetConjunctive()on field definitions.