Skip to content

Support multiple filters in aggregations#2568

Open
TravelCurry02 wants to merge 17 commits intoash-project:mainfrom
TravelCurry02:support-multiple-filters-in-aggregations
Open

Support multiple filters in aggregations#2568
TravelCurry02 wants to merge 17 commits intoash-project:mainfrom
TravelCurry02:support-multiple-filters-in-aggregations

Conversation

@TravelCurry02
Copy link
Contributor

@TravelCurry02 TravelCurry02 commented Feb 17, 2026

Contributor checklist

Leave anything that you believe does not apply unchecked.

  • I accept the AI Policy, or AI was not used in the creation of this PR.
  • Bug fixes include regression tests
  • Chores
  • Documentation changes
  • Features include unit/acceptance tests
  • Refactoring
  • Update dependencies

Overview

This PR implements support for multiple filter lines in aggregate definitions, matching the behavior of read actions. Previously, attempting to use multiple filters in an aggregate would result in the error: "Multiple values for key :filter".

Issue: #1265

What Changed

Before

aggregates do
  count :total_students_this_month, :students do
    filter expr(inserted_at >= fragment("date_trunc('month', now())"))
    filter expr(inserted_at < fragment("date_trunc('month', now()) + interval '1 month'"))
    # Error: Multiple values for key `:filter`
  end
end

After

aggregates do
  count :total_students_this_month, :students do
    filter expr(inserted_at >= fragment("date_trunc('month', now())"))
    filter expr(inserted_at < fragment("date_trunc('month', now()) + interval '1 month'"))
    # Works! Both filters are combined with AND
  end
end

Implementation Details

Files Modified

  1. lib/ash/resource/aggregate/aggregate.ex

    • Added filters: [] field to struct to store multiple filter entities
    • Added concat_filters/1 to combine multiple filters with AND (single code path for one or many)
    • Added combine_filter/2 helper to merge with existing filter when present (backward compatibility)
    • Updated transform/1 to call concat_filters after relationship path normalization
    • Updated type spec to include filters: [any]
  2. lib/ash/resource/dsl.ex

    • Added filters: [@filter] entity to all 9 aggregate types (count, first, max, min, sum, avg, exists, custom, list)
    • Removed filter from schema in aggregate entities to avoid DSL ambiguity
  3. test/resource/aggregates_test.exs

    • Added 6 test cases in describe "multiple filters" block:
      • Basic multiple filter support
      • Filter combination verification
      • Backward compatibility (single filter)
      • All aggregate types support
      • Runtime execution test with real data
      • Edge case (empty filters)

How It Works

  1. DSL level: Aggregate blocks accept multiple filter expr(...) lines as repeatable entities (same pattern as read actions).
  2. Storage: Each filter line is stored in the filters: [] list on the aggregate struct.
  3. Combination: concat_filters/1 combines all filters using Ash.Query.BooleanExpression.new(:and, ...).
  4. Result: The combined filter is stored in aggregate.filter, which existing code continues to use.

Backward Compatibility

  • Single filter expr(...) still works (same code path; when rest is empty, reduce returns the single filter).
  • Existing aggregates with one filter are unchanged.
  • The filter field on the struct remains; downstream code is unchanged.

Testing

All tests pass, including:

  • Compilation and structure tests
  • Runtime execution tests with real data
  • Backward compatibility tests
  • Edge case tests (empty filters)

Related Patterns

This implementation mirrors existing patterns:

  • Read actions: filters: [@filter] entity → concat_filters → combined filter
  • Join filters: Aggregate already had join_filters: []; this adds the same list pattern for main filters

TravelCurry02 and others added 8 commits January 26, 2026 13:23
Updated compile error handling to correctly point to the second invocation of 'use Ash.Domain' instead of the defmodule line. Enhanced error messages for clarity and consistency in Ash.Domain.Interface. Added tests to verify correct error line and message content.
- Add filters entity to all aggregate types
- Combine multiple filters with AND, matching read actions behavior
- Maintain backward compatibility with single filter
- Add comprehensive tests

Fixes ash-project#1265
@TravelCurry02 TravelCurry02 marked this pull request as draft February 18, 2026 20:02
@TravelCurry02 TravelCurry02 marked this pull request as ready for review February 18, 2026 20:02
@TravelCurry02 TravelCurry02 marked this pull request as draft February 18, 2026 20:03
@TravelCurry02 TravelCurry02 marked this pull request as ready for review February 18, 2026 20:09
@TravelCurry02 TravelCurry02 marked this pull request as draft February 18, 2026 20:53
@TravelCurry02 TravelCurry02 marked this pull request as ready for review February 18, 2026 20:56
@TravelCurry02 TravelCurry02 marked this pull request as draft February 18, 2026 21:05
@TravelCurry02 TravelCurry02 marked this pull request as ready for review February 18, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant