AE
Ash Elixir•3y ago
Blibs

Sorting with calculation result giver "Argument value is required" error

I have the following query:
Markets.Property.Offeror
|> Ash.Query.filter(
fragment("? <% ?", ^value, full_name) or
fragment("? <% ?", ^value, email) or fragment("? <% ?", ^value, phone_number)
)
|> Ash.Query.load(:full_name)
|> Ash.Query.load(full_name_similarity: %{value: value})
|> Ash.Query.load(email_similarity: %{value: value})
|> Ash.Query.load(phone_number_similarity: %{value: value})
|> Ash.Query.load(:similarity)
|> Ash.Query.sort(similarity: :desc, full_name: :desc)
|> Markets.read!()
Markets.Property.Offeror
|> Ash.Query.filter(
fragment("? <% ?", ^value, full_name) or
fragment("? <% ?", ^value, email) or fragment("? <% ?", ^value, phone_number)
)
|> Ash.Query.load(:full_name)
|> Ash.Query.load(full_name_similarity: %{value: value})
|> Ash.Query.load(email_similarity: %{value: value})
|> Ash.Query.load(phone_number_similarity: %{value: value})
|> Ash.Query.load(:similarity)
|> Ash.Query.sort(similarity: :desc, full_name: :desc)
|> Markets.read!()
In my resource I have these calculations:
calculations do
calculate :full_name, :string, expr(string_join([first_name, surname], " "))

calculate :full_name_similarity, :float, expr(trigram_similarity(full_name, ^arg(:value))) do
argument :value, :string, allow_nil?: false
end

calculate :email_similarity, :float, expr(trigram_similarity(email, ^arg(:value))) do
argument :value, :string, allow_nil?: false
end

calculate :phone_number_similarity, :float, expr(trigram_similarity(phone_number, ^arg(:value))) do
argument :value, :string, allow_nil?: false
end

calculate :similarity, :float, expr(fragment("greatest(?, ?, ?)", full_name_similarity, email_similarity, phone_number_similarity))
end
calculations do
calculate :full_name, :string, expr(string_join([first_name, surname], " "))

calculate :full_name_similarity, :float, expr(trigram_similarity(full_name, ^arg(:value))) do
argument :value, :string, allow_nil?: false
end

calculate :email_similarity, :float, expr(trigram_similarity(email, ^arg(:value))) do
argument :value, :string, allow_nil?: false
end

calculate :phone_number_similarity, :float, expr(trigram_similarity(phone_number, ^arg(:value))) do
argument :value, :string, allow_nil?: false
end

calculate :similarity, :float, expr(fragment("greatest(?, ?, ?)", full_name_similarity, email_similarity, phone_number_similarity))
end
When I run this query, I will get this error:
** (Ash.Error.Unknown) Unknown Error

* Argument value is required
** (Ash.Error.Unknown) Unknown Error

* Argument value is required
The query works fine I if remove the similarity: desc from the sort function. Any idea why?
7 Replies
Blibs
BlibsOP•3y ago
Here is the full stacktrace of the error:
ZachDaniel
ZachDaniel•3y ago
So, you're chaining calculations that require arguments, meaning you're going to have to thread them through
calculate :similarity, :float, expr(fragment("greatest(?, ?, ?)", full_name_similarity(value: arg(:value)), email_similarity(value: arg(:value)), phone_number_similarity(value: arg(:value)))) do
argument :value, :string, allow_nil?: false
end
calculate :similarity, :float, expr(fragment("greatest(?, ?, ?)", full_name_similarity(value: arg(:value)), email_similarity(value: arg(:value)), phone_number_similarity(value: arg(:value)))) do
argument :value, :string, allow_nil?: false
end
I think the misunderstanding is here:
Markets.Property.Offeror
|> Ash.Query.filter(
fragment("? <% ?", ^value, full_name) or
fragment("? <% ?", ^value, email) or fragment("? <% ?", ^value, phone_number)
)
|> Ash.Query.load(:full_name)
|> Ash.Query.load(full_name_similarity: %{value: value}) # <- this doesn't make `:similarity` work below
|> Ash.Query.load(email_similarity: %{value: value})
|> Ash.Query.load(phone_number_similarity: %{value: value})
|> Ash.Query.load(:similarity)
|> Ash.Query.sort(similarity: :desc, full_name: :desc)
|> Markets.read!()
Markets.Property.Offeror
|> Ash.Query.filter(
fragment("? <% ?", ^value, full_name) or
fragment("? <% ?", ^value, email) or fragment("? <% ?", ^value, phone_number)
)
|> Ash.Query.load(:full_name)
|> Ash.Query.load(full_name_similarity: %{value: value}) # <- this doesn't make `:similarity` work below
|> Ash.Query.load(email_similarity: %{value: value})
|> Ash.Query.load(phone_number_similarity: %{value: value})
|> Ash.Query.load(:similarity)
|> Ash.Query.sort(similarity: :desc, full_name: :desc)
|> Markets.read!()
Each calculation is evaluated independently of what is already loaded
Blibs
BlibsOP•3y ago
Hmm, but in this case, why does the query works if I just don't add the sort line? And I also tried that change and I still get the value is required error:
** (Ash.Error.Unknown) Unknown Error

* Argument value is required
at sort
(ash 2.6.27) lib/ash/error/error.ex:331: Ash.Error.to_ash_error/3
(elixir 1.14.4) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(ash 2.6.27) lib/ash/query/query.ex:2266: Ash.Query.add_error/3
(elixir 1.14.4) src/elixir.erl:309: anonymous fn/4 in :elixir.eval_external_handler/1
(stdlib 4.3) erl_eval.erl:748: :erl_eval.do_apply/7
(elixir 1.14.4) src/elixir.erl:294: :elixir.eval_forms/4
(elixir 1.14.4) lib/module/parallel_checker.ex:110: Module.ParallelChecker.verify/1
(iex 1.14.4) lib/iex/evaluator.ex:329: IEx.Evaluator.eval_and_inspect/3
(iex 1.14.4) lib/iex/evaluator.ex:303: IEx.Evaluator.eval_and_inspect_parsed/3
(iex 1.14.4) lib/iex/evaluator.ex:292: IEx.Evaluator.parse_eval_inspect/3
(iex 1.14.4) lib/iex/evaluator.ex:187: IEx.Evaluator.loop/1
(iex 1.14.4) lib/iex/evaluator.ex:32: IEx.Evaluator.init/4
(stdlib 4.3) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
(ash 2.6.27) lib/ash/error/error.ex:463: Ash.Error.choose_error/2
(ash 2.6.27) lib/ash/error/error.ex:218: Ash.Error.to_error_class/2
(ash 2.6.27) lib/ash/actions/read.ex:181: Ash.Actions.Read.do_run/3
(ash 2.6.27) lib/ash/actions/read.ex:90: Ash.Actions.Read.run/3
(ash 2.6.27) lib/ash/api/api.ex:1378: Ash.Api.read!/3
iex:241: (file)
** (Ash.Error.Unknown) Unknown Error

* Argument value is required
at sort
(ash 2.6.27) lib/ash/error/error.ex:331: Ash.Error.to_ash_error/3
(elixir 1.14.4) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(ash 2.6.27) lib/ash/query/query.ex:2266: Ash.Query.add_error/3
(elixir 1.14.4) src/elixir.erl:309: anonymous fn/4 in :elixir.eval_external_handler/1
(stdlib 4.3) erl_eval.erl:748: :erl_eval.do_apply/7
(elixir 1.14.4) src/elixir.erl:294: :elixir.eval_forms/4
(elixir 1.14.4) lib/module/parallel_checker.ex:110: Module.ParallelChecker.verify/1
(iex 1.14.4) lib/iex/evaluator.ex:329: IEx.Evaluator.eval_and_inspect/3
(iex 1.14.4) lib/iex/evaluator.ex:303: IEx.Evaluator.eval_and_inspect_parsed/3
(iex 1.14.4) lib/iex/evaluator.ex:292: IEx.Evaluator.parse_eval_inspect/3
(iex 1.14.4) lib/iex/evaluator.ex:187: IEx.Evaluator.loop/1
(iex 1.14.4) lib/iex/evaluator.ex:32: IEx.Evaluator.init/4
(stdlib 4.3) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
(ash 2.6.27) lib/ash/error/error.ex:463: Ash.Error.choose_error/2
(ash 2.6.27) lib/ash/error/error.ex:218: Ash.Error.to_error_class/2
(ash 2.6.27) lib/ash/actions/read.ex:181: Ash.Actions.Read.do_run/3
(ash 2.6.27) lib/ash/actions/read.ex:90: Ash.Actions.Read.run/3
(ash 2.6.27) lib/ash/api/api.ex:1378: Ash.Api.read!/3
iex:241: (file)
But now it says that it is in the sort
ZachDaniel
ZachDaniel•3y ago
Yeah, so you need to provide the calculation arguments What I think you want here:
Markets.Property.Offeror
|> Ash.Query.filter(
fragment("? <% ?", ^value, full_name) or
fragment("? <% ?", ^value, email) or fragment("? <% ?", ^value, phone_number)
)
|> Ash.Query.load(:full_name)
# not sure if you need these?
#|> Ash.Query.load(full_name_similarity: %{value: value})
#|> Ash.Query.load(email_similarity: %{value: value})
#|> Ash.Query.load(phone_number_similarity: %{value: value})
|> Ash.Query.load(similarity: %{value: value})
|> Ash.Query.sort(similarity: {:desc, %{value: value}}, full_name: :desc)
|> Markets.read!()
Markets.Property.Offeror
|> Ash.Query.filter(
fragment("? <% ?", ^value, full_name) or
fragment("? <% ?", ^value, email) or fragment("? <% ?", ^value, phone_number)
)
|> Ash.Query.load(:full_name)
# not sure if you need these?
#|> Ash.Query.load(full_name_similarity: %{value: value})
#|> Ash.Query.load(email_similarity: %{value: value})
#|> Ash.Query.load(phone_number_similarity: %{value: value})
|> Ash.Query.load(similarity: %{value: value})
|> Ash.Query.sort(similarity: {:desc, %{value: value}}, full_name: :desc)
|> Markets.read!()
The arguments need to be provided to the sort as well
Blibs
BlibsOP•3y ago
Ah, I see I guess I don't even need the load for the similarity in this case right? Since sort will already load it
ZachDaniel
ZachDaniel•3y ago
Sort won't load it but it will sort by it But the concepts are isolated you don't have to load something to sort by it, and sorting by it won't load it If you want both (to load it and sort by it) then you have to do both
Blibs
BlibsOP•3y ago
got it, makes sense thanks again 🙂

Did you find this page helpful?