-
Ecto.Multi기술 동향 2020. 10. 6. 14:21
Ecto.Multi는 여러 Repo 작업을 그룹화하기위한 데이터 구조입니다.
Ecto.Multi은 가능한 하나의 데이터베이스 트랜잭션에서 수행하고 각 insert/update/delete등의 각 작업은 호출 시, 실행되지 않은 채로 MapSet에서 관리 되어야 합니다. 각 작업은 고유한 key를 가지며 성공 또는 실패의 경우에 그 결과를 식별하는 이름이 지정됩니다.
모든 작업은 추가 된 순서대로 실행됩니다.
%Ecto.Multi{}를 사용하여 유형 일치를 패턴화할 수 있지만 필드에 액세스하거나 직접 수정하는 것은 권장되지 않습니다.
Ecto.Multi.to_list / 1은 내부 검사에 사용할 수있는 구조의 표준 표현을 반환합니다.
pills_attrs |> Stream.map(fn pill -> change_pill(prescription, pill) end) |> Stream.map(fn pill_changeset -> key = "pill:#{pill_changeset.changes.name}" Ecto.Multi.insert(Ecto.Multi.new(), key, pill_changeset) end) |> Enum.reduce(Ecto.Multi.new(), &Ecto.Multi.append/2) |> Repo.transaction() |> case do {:ok, _pill} -> {:ok, prescription} {:error, _failed_operation, failed_value, _changes_so_far} -> {:error, failed_value} end
Ecto.Multi 는 MapSet<>의 구현체입니다.
여러 개의 Multi를 만들어서 append 또는 prepend 하여 Repo.transaction/1 으로 한 번에 처리할 때 사용합니다.
Stream.map/3 등을 사용하여 Ecto.Multi를 manipulate하여 사용합니다.
혹시 이전 쿼리의 리턴 값이 다음 쿼리에 필요한 경우에는 다음과 같이 처리합니다.
Ecto.Multi.new() |> Ecto.Multi.insert(:insert_prescription, changes_prescription(user, doctor, prescription_attrs)) |> Ecto.Multi.run(:insert_pills, fn _repo, %{insert_prescription: prescription} -> ...... |> Repo.transaction() |> case do {:ok, prescription} -> {:ok, prescription.insert_prescription} {:error, _failed_operation, failed_value, _changes_so_far} -> {:error, failed_value} end # prescription.insert_prescription로 빼낸 것을 주목하세요 ^^
Ecto.Multi.run/3 함수를 사용하면 이전 쿼리의 결과 값을 name key로 받아올 수 있습니다.
Ecto.Multi는 transaction이므로 한 번에 많은 데이터를 여러 쿼리를 사용해서 관리할 때 편합니다.
명시적으로 rollback함수를 호출할 수도 있습니다.
insert_all을 사용할 수도 있지만 이 경우에는 timestampt() 로 생성한 updated_at / created_at을 처리해 주지 않습니다.
'기술 동향' 카테고리의 다른 글
Process Register (0) 2021.04.05 Ecto Composable Query (0) 2020.11.16 History of Erlang (0) 2020.06.25 Raft Consensus Algorithm (0) 2020.06.25 Elixir Technical Advantages (0) 2020.06.08