So I'm trying to allow search on various fields in a database, this is the situation:
- A user wants to find all posts that were created by users who joined before October 2020
- A user wants to find all posts that were created by users who joined after October 2020
- A user wants to find all posts that were created by users who joined on October 5th 2020
normally I would need to write various verions of this query like so:
def before_date(query, date) do
query
|> where([posts, users], users.inserted_at < ^date))
end
def after_date(query, date) do
query
|> where([posts, users], users.inserted_at > ^date))
end
def on_date(query, date) do
query
|> where([posts, users], users.inserted_at == ^date))
end
Then to filter on the posts date themselves, I would need to write those queries over again and uses posts.inserted_at instead.
Therefore I'm looking for a way to dynamically compare items inside and Ecto Query.
I found this question: Create Ecto query with dynamic operators
but it didn't compile as it complained that the query was not valid:
== Compilation error in file lib/mmsapi/liquid/search/filters.ex ==
** (CompileError) lib/mmsapi/liquid/search/filters.ex:338: invalid call operator(field(o, ^field_name), ^value)
expanding macro: Liquid.Search.Filters.custom_where/4
so a slight modification and got to this, by replacing the variable operator with an actual operator:
defmacrop custom_where(t, f, v, :==) do
{:==, [context: Elixir, import: Kernel],
[
{:field, [], [t, {:^, [], [f]}]},
{:^, [], [v]}
]}
end
def compare_field(query, field_name, value, operator) do
query
|> where([o], ^custom_where(o, field_name, value, operator))
end
However with that I get this error:
== Compilation error in file lib/mmsapi/liquid/search/filters.ex ==
** (CompileError) lib/mmsapi/liquid/search/filters.ex:327: cannot use ^field_name outside of match clauses
This is the kind of code I'm trying to achieve:
field_name = :inserted_at
value = DateTime.utc_now()
operator = :==
query
|> where([posts, users], custom_where(users, field_name, value, operator))
Any assistance would be most appreciated, and thank you in advanced!