I have an List of metadata items that has the following format:
[%{id: "id1"}, %{id: "id2"}, %{id: "id3"}]
I am trying to do a query using a join with this list, the idea here is to pick posts who have this specific metadata ids.
relevant_metadata_ids = [%{id: "id1"}, %{id: "id2"}, %{id: "id3"}]
posts =
Post
|> join(:inner, [post], meta in ^relevant_metadata_ids,
on: fragment("?->>'meta_id'", post.metadata) == meta.id
)
However, it seems I can't quite do this, as I get the following error:
** (Protocol.UndefinedError) protocol Ecto.Queryable not implemented for [%{meta_upload_id: "id1"}] of type List. This protocol is implemented for the following type(s): Atom, BitString, Ecto.Query, Ecto.SubQuery, Tuple
Is there a way to leverage the information I have in the list and use it in an Ecto Query?
I have found a way around my problem. If using join
is not a viable option, then perhaps I can use another construct. This is the case for where
.
By changing the list List of metadata items to just the ids:
[%{id: "id1"}, %{id: "id2"}, %{id: "id3"}]
# becomes
["id1", "id2", "id3"]
I can then transform my query to use a where
clause:
relevant_metadata_ids = ["id1", "id2", "id3"]
posts =
Post
|> where([post], fragment("?->>'meta_id'", post.metadata) in ^relevant_metadata_ids)
|> ...
This works as it seems to be quite fast. If the ids inside of relevant_metadata_ids
are not repeated, its even better.
I will eventually have to join with a correspondent table though, but this does the job.