Trying to access nested aggregates, but get subquery exception

Hello guys.

I’m trying to access nested aggregates.

My idea here is to have a count to know the number of “offers”. I tried different ways, using calculation and even using count inside expr. The error is always the same when I load :total_no_deals on my User module

Anyone can help me?

Module User

# ...

has_many :disposition_agent_to, Property do
  destination_attribute :disposition_agent_id
end

# ...

aggregates do
  # ...
  
  count :total_no_deals, :disposition_agent_to do
    filter expr(total_offers == 0)
  end
end

Module Property

defmodule Marketplace.Accounts.Property do
  @moduledoc false

  use Ash.Resource,
    data_layer: AshPostgres.DataLayer

  attributes do
    uuid_primary_key :id

    # ...
  end

  relationships do
    alias Marketplace.Accounts.{User, Offer}

    belongs_to :disposition_agent, User do
      allow_nil? true
      attribute_writable? true
    end

    has_many :offers, Offer
  end

  aggregates do
    count :total_offers, :offers
  end

  # ...
  
  actions do
    defaults [:read]
  end
end

Module Offer

defmodule Marketplace.Accounts.Offer do
  @moduledoc false

  use Ash.Resource,
    data_layer: AshPostgres.DataLayer

  attributes do
    uuid_primary_key :id
  end

  relationships do
    alias Marketplace.Accounts.Property

    belongs_to :property, Property, allow_nil?: false
  end

  postgres do
    table "offers"

    repo Marketplace.Repo
  end

  actions do
    defaults [:read]
  end
end

iex(0) > Marketplace.Markets.load(user, [:total_no_deals])

Error:

 %Ash.Error.Unknown{
   errors: [
     %Ash.Error.Unknown.UnknownError{
       error: "** (Ecto.SubQueryError) the following exception happened when compiling a subquery.\n\n    ** (Ecto.SubQueryError) the following exception happened when compiling a subquery.\n    \n        ** (Ecto.QueryError) deps/ash_postgres/lib/aggregate.ex:1049: field `property_id` in `select` does not exist in schema Marketplace.Accounts.Offer in query:\n        \n        from o0 in Marketplace.Accounts.Offer,\n          as: 0,\n          where: parent_as(0).id == as(0).property_id,\n          group_by: [o0.property_id],\n          select: %{\n          total_offers:\n            type(\n              coalesce(\n                count(type(as(0).id, {:parameterized, Ash.Type.UUID.EctoType, []})),\n                type(^0, {:parameterized, Ash.Type.Integer.EctoType, []})\n              ),\n              {:parameterized, Ash.Type.Integer.EctoType, []}\n            ),\n          property_id: map(o0, [:property_id]).property_id\n        }\n        \n    \n    The subquery originated from the following query:\n    \n    from p0 in Marketplace.Accounts.Property,\n      as: 0,\n      left_lateral_join: o1 in subquery(from o0 in Marketplace.Accounts.Offer,\n      as: 0,\n      where: parent_as(0).id == as(0).property_id,\n      group_by: [o0.property_id],\n      select: merge(\n      %{\n        total_offers:\n          type(\n            coalesce(\n              count(type(as(0).id, {:parameterized, Ash.Type.UUID.EctoType, []})),\n              type(^0, {:parameterized, Ash.Type.Integer.EctoType, []})\n            ),\n            {:parameterized, Ash.Type.Integer.EctoType, []}\n          )\n      },\n      map(o0, [:property_id])\n    )),\n      as: 1,\n      on: true,\n      where: type(\n      as(0).status,\n      {:parameterized, Ash.Type.Atom.EctoType, one_of: [:draft, :open, :pending, :sold, :inactive]}\n    ) ==\n      type(\n        ^\"open\",\n        {:parameterized, Ash.Type.Atom.EctoType, one_of: [:draft, :open, :pending, :sold, :inactive]}\n      ),\n      where: type(\n      coalesce(as(1).total_offers, type(^0, {:parameterized, Ash.Type.Integer.EctoType, []})),\n      {:parameterized, Ash.Type.Integer.EctoType, []}\n    ) == type(^0, {:parameterized, Ash.Type.Integer.EctoType, []}),\n      where: parent_as(0).id == as(0).disposition_agent_id,\n      group_by: [p0.disposition_agent_id],\n      select: merge(\n      merge(merge(merge(map(p0, [:disposition_agent_id]), %{}), %{}), %{\n        total_no_deals:\n          type(\n            coalesce(\n              count(type(as(0).id, {:parameterized, Ash.Type.UUID.EctoType, []})),\n              type(^0, {:parameterized, Ash.Type.Integer.EctoType, []})\n            ),\n            {:parameterized, Ash.Type.Integer.EctoType, []}\n          )\n      }),\n      map(p0, [:disposition_agent_id])\n    )\n    \n\nThe subquery originated from the following query:\n\nfrom u0 in Marketplace.Accounts.User,\n  as: 0,\n  left_lateral_join: p1 in subquery(from p0 in Marketplace.Accounts.Property,\n  as: 0,\n  left_lateral_join: o1 in subquery(from o0 in Marketplace.Accounts.Offer,\n  as: 0,\n  where: parent_as(0).id == as(0).property_id,\n  group_by: [o0.property_id],\n  select: merge(\n  %{\n    total_offers:\n      type(\n        coalesce(\n          count(type(as(0).id, {:parameterized, Ash.Type.UUID.EctoType, []})),\n          type(^0, {:parameterized, Ash.Type.Integer.EctoType, []})\n        ),\n        {:parameterized, Ash.Type.Integer.EctoType, []}\n      )\n  },\n  map(o0, [:property_id])\n)),\n  as: 1,\n  on: true,\n  where: type(\n  as(0).status,\n  {:parameterized, Ash.Type.Atom.EctoType, one_of: [:draft, :open, :pending, :sold, :inactive]}\n) ==\n  type(\n    ^\"open\",\n    {:parameterized, Ash.Type.Atom.EctoType, one_of: [:draft, :open, :pending, :sold, :inactive]}\n  ),\n  where: type(\n  coalesce(as(1).total_offers, type(^0, {:parameterized, Ash.Type.Integer.EctoType, []})),\n  {:parameterized, Ash.Type.Integer.EctoType, []}\n) == type(^0, {:parameterized, Ash.Type.Integer.EctoType, []}),\n  where: parent_as(0).id == as(0).disposition_agent_id,\n  group_by: [p0.disposition_agent_id],\n  select: merge(\n  merge(merge(merge(map(p0, [:disposition_agent_id]), %{}), %{}), %{\n    total_no_deals:\n     " <> ...,

Using: Elixir 1.16.0 (compiled with Erlang/OTP 24)

Are you on the latest ash and ash_postgres versions? A subquery error is a bug in ash_postgres. It was a recent change to support referencing nested aggregates. If upgrading doesn’t resolve the issue, please open an issue on the ash_postgres repo.

Great, my bad! Upgrade really solve my issue. Thank you very much

1 Like