Created
September 5, 2023 13:51
-
-
Save lessless/557ff48af24394d2b049ffebb79df82f to your computer and use it in GitHub Desktop.
ecto find_non_existing_set
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# courtesy @mrdotb | |
defmodule T do | |
import Ecto.Query | |
alias Your.Repo | |
@doc """ | |
Use runtime data as an adhoc db table to join to data. | |
`types` need to be a compile time string literal. | |
`values` can be runtime supplied. | |
## Example | |
data = [%{id: 1, text: "hey"}, %{id: 2, text: "ho"}] | |
from a in Table, | |
join: b in jsonb_recordset("id uuid, text text", data), | |
on: a.id == b.id | |
""" | |
defmacro jsonb_recordset(types, values) do | |
quote do | |
fragment( | |
unquote("(SELECT * FROM json_to_recordset(?) as t(#{types}))"), | |
^unquote(values) | |
) | |
end | |
end | |
def find_non_existing_set(set_list) do | |
pairs = Enum.map(set_list, fn {id, another_id} -> | |
%{id: id, another_id: another_id} | |
end) | |
"pairs" | |
|> with_cte("pairs", as: jsonb_recordset("id int, another_id int", pairs)) | |
|> join(:left, [pair], item in "items", on: item.id == pair.id and item.another_id == pair.another_id) | |
|> where([_pair, item], is_nil(item)) | |
|> select([pair, _item], {pair.id, pair.another_id}) | |
|> Repo.all() | |
end | |
def tests do | |
find_non_existing_set([{1, 2}, {3, 4}, {1337, 1337}]) | |
# [{1337, 1337}] | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment