Ecto with ordinality

We want to query the post where the id is 1, 2, 4, 3 and keep this order The best solution to do that using postgres is WITH ORDINALITY

SELECT p.*
FROM posts p
JOIN unnest('{1,2,4,3}'::int[]) WITH ORDINALITY t(id, ord) USING (id)
ORDER BY t.order;

Complete query

def list_post_where_id_in_order(ids) do
  query =
    from post in Post,
      inner_join:
        ordinality in fragment(
          "SELECT * FROM UNNEST(?::int[]) WITH ORDINALITY as ordinality (id, num)",
          ^ids
        ),
      on: post.id == ordinality.id,
      order_by: [asc: ordinality.num]

  Repo.all(query)
end

iex> list_post_where_id_in_order([1, 2, 4, 3])

Composable query

def post_by_id_in_order(query, ids) do
  query
  |> join(
    :inner,
    [post],
    ordinality in fragment(
      "SELECT * FROM UNNEST(?::int[]) WITH ORDINALITY as ordinality (id, num)",
      ^ids
    ),
    on: post.id == ordinality.id,
    as: :ordinality
  )
  |> order_by([post, ordinality: ordinality], asc: ordinality.num)
end

iex> Post |> post_by_id_in_order([1, 2, 4, 3]) |> Repo.all()