Hi Everyone!
I’d really appreciate if I could get some help with this issue I ran into.
I’m trying to allow searching 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 write various versions 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 an Ecto Query.
I found this question: Create Ecto query with dynamic operators
but it didn’t compile as the compile 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))
Or event better yet, so that I could use it for dynamic joins:
join_name = :users
field_name = :inserted_at
value = DateTime.utc_now()
operator = :==
query
|> where([posts, {join_name, u}], custom_where(u, field_name, value, operator))
Any assistance would be most appreciated, and thank you in advanced!