joehua87
Remove `and true` in dynamic query reduce
When using reduce in dynamic query, like discussed in the Ecto docs here, it produce output like this:
where: true and (true and e0.avg_rating > ^3)
The problems it that it make expression longer and harder to maintain test
Does anyone have ideas to reduce this to:
where: e0.avg_rating > ^3
Marked As Solved
chrismcg
I wouldn’t use inspect here as it’s representation could change (see [1] for an example of this).
I think you could make the initial value of reduce nil and then pattern match on that rather than dynamic(true) representation.
e.g.
defp join_exp(nil, exp) -> exp
defp join_exp(acc, exp) -> dynamic(^acc and ^exp)
[1] Multi-letter sigils by wojtekmach · Pull Request #9826 · elixir-lang/elixir · GitHub
Also Liked
sb8244
I’ve thought about this for a recent project but didn’t implement it, because I decided it wasn’t worth the code for SQL vanity purpose.
In your reducer function, you could case on the accumulator condition and, if nil, produce a query without the and. The benefit of using “true and” is that your reducer doesn’t need to care what the accumulator is.
I haven’t tried it but I think this would work.
joehua87
Thank you @sb8244! It’s simpler than I thought, just made it ![]()
Before:
defp parse_item({compare_type, value}, acc, field_name) do
case compare_type do
:eq -> dynamic([p], ^acc and field(p, ^field_name) == ^value)
:gt -> dynamic([p], ^acc and field(p, ^field_name) > ^value)
:lt -> dynamic([p], ^acc and field(p, ^field_name) < ^value)
:gte -> dynamic([p], ^acc and field(p, ^field_name) >= ^value)
:lte -> dynamic([p], ^acc and field(p, ^field_name) <= ^value)
_ -> acc
end
end
After:
defp parse_item({compare_type, value}, acc, field_name) do
case compare_type do
:eq -> join_exp(acc, dynamic([p], field(p, ^field_name) == ^value))
:gt -> join_exp(acc, dynamic([p], field(p, ^field_name) > ^value))
:lt -> join_exp(acc, dynamic([p], field(p, ^field_name) < ^value))
:gte -> join_exp(acc, dynamic([p], field(p, ^field_name) >= ^value))
:lte -> join_exp(acc, dynamic([p], field(p, ^field_name) <= ^value))
_ -> acc
end
end
defp join_exp(acc, exp) do
case inspect(acc) do
"dynamic([], true)" ->
exp
_ ->
dynamic(^acc and ^exp)
end
end
dimitarvp
Last Post!
joehua87
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









