Filter search results

You can filter searches using different methods, each suited to specific scenarios. You can apply filters at the query level, using boolean query clauses and post_filter and aggregation level filters, as follows:

  • Query-level filtering: Apply boolean query filter clauses to filter search hits and aggregations, such as to narrow results to specific categories or brands.
  • Post-filter filtering: Use post_filter to refine search hits based on user selections while preserving all aggregation options.
  • Aggregation-level filtering: Adjust specific aggregations based on selected filters without impacting other aggregations.

Query-level filtering with Boolean queries

Use a boolean query with a filter clause to apply filters to both search hits and aggregations. For example, if a shopper searches for smartphones from BrandA, a Boolean query can restrict results to only those smartphones from BrandA. The following steps guide you through query-level filtering.

  1. Create an index electronics and provide the mapping using the following request:
  1. PUT /electronics
  2. {
  3. "mappings": {
  4. "properties": {
  5. "brand": { "type": "keyword" },
  6. "category": { "type": "keyword" },
  7. "price": { "type": "float" },
  8. "features": { "type": "keyword" }
  9. }
  10. }
  11. }

copy

  1. Add documents to the electronics index using the following request:
  1. PUT /electronics/_doc/1?refresh
  2. {
  3. "brand": "BrandA",
  4. "category": "Smartphone",
  5. "price": 699.99,
  6. "features": ["5G", "Dual Camera"]
  7. }
  8. PUT /electronics/_doc/2?refresh
  9. {
  10. "brand": "BrandA",
  11. "category": "Laptop",
  12. "price": 1199.99,
  13. "features": ["Touchscreen", "16GB RAM"]
  14. }
  15. PUT /electronics/_doc/3?refresh
  16. {
  17. "brand": "BrandB",
  18. "category": "Smartphone",
  19. "price": 799.99,
  20. "features": ["5G", "Triple Camera"]
  21. }

copy

  1. Apply a boolean filter query to display only smartphones from BrandA using the following request:
  1. GET /electronics/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": [
  6. { "term": { "brand": "BrandA" }},
  7. { "term": { "category": "Smartphone" }}
  8. ]
  9. }
  10. }
  11. }

copy

Narrowing results using post-filter while preserving aggregation visibility

Use post_filter to limit search hits while preserving all aggregation options. For example, if a shopper selects BrandA, results are filtered to show only BrandA products while maintaining the visibility of all brand options in the aggregations, as shown in the following example request:

  1. GET /electronics/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": { "term": { "category": "Smartphone" }}
  6. }
  7. },
  8. "aggs": {
  9. "brands": {
  10. "terms": { "field": "brand" }
  11. }
  12. },
  13. "post_filter": {
  14. "term": { "brand": "BrandA" }
  15. }
  16. }

copy

The result should show BrandA smartphones in the search hits and all brands in the aggregations.

Refining aggregations with aggregation-level filtering

You can use aggregation-level filtering to apply filters to specific aggregations without affecting the main aggregation to which they belong.

For example, you can use aggregation-level filtering to filter the price_ranges aggregation based on selected brands, BrandA and BrandB, without affecting the main price_ranges aggregation, as shown in the following example request. This displays price ranges relevant to the selected brands while also displaying overall price ranges for all products.

  1. GET /electronics/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": { "term": { "category": "Smartphone" }}
  6. }
  7. },
  8. "aggs": {
  9. "price_ranges": {
  10. "range": {
  11. "field": "price",
  12. "ranges": [
  13. { "to": 500 },
  14. { "from": 500, "to": 1000 },
  15. { "from": 1000 }
  16. ]
  17. }
  18. },
  19. "filtered_brands": {
  20. "filter": {
  21. "terms": { "brand": ["BrandA", "BrandB"] }
  22. },
  23. "aggs": {
  24. "price_ranges": {
  25. "range": {
  26. "field": "price",
  27. "ranges": [
  28. { "to": 500 },
  29. { "from": 500, "to": 1000 },
  30. { "from": 1000 }
  31. ]
  32. }
  33. }
  34. }
  35. }
  36. }
  37. }

copy