지난 글에 이어서 Ash 프레임워크에서 데이터를 쿼리하는 방법을 알아본다.
먼저 Ticket 리소스 전체 목록을 가져오는 코드는 다음과 같다.
Ash.read!(Helpdesk.Support.Ticket)
그러나 지금 상황에서 코드를 바로 실행하면 다음과 같은 오류가 발생한다.
iex> Ash.read!(Helpdesk.Support.Ticket)
** (Ash.Error.Framework)
Bread Crumbs:
> Error returned from: Helpdesk.Support.Ticket.read
Framework Error
* No data provided to resource Elixir.Helpdesk.Support.Ticket. Perhaps you are missing a call to `Ash.DataLayer.Simple.set_data/2`?.
Another common cause of this is failing to add a data layer for a resource. You can add a data layer like so:
`use Ash.Resource, data_layer: Ash.DataLayer.Ets`
Ticket 리소스에 대해 데이터 레이어가 없다는 얘기다. 지금까지 리소스를 정의만 했지 어디에 저장할지는 정의하지 않았다. 리소스를 어디에 저장할 지 데이터 레이어를 지정하면 해결되지만 그 전에 데이터 레이어가 없는 경우에는 어떻게 다룰 수 있는지 알아 보자.
데이터 레이어가 없는 리소스는 암시적으로 Ash.DataLayer.Simple 를 사용한다. 이 데이터는 어디에도 영속화 되지 않으며 쿼리가 실행될 때 같이 제공되어야 한다.
조회를 시험해 볼 데이터를 먼저 만든다.
iex> tickets =
for i <- 0..5 do
ticket =
Helpdesk.Support.Ticket
|> Ash.Changeset.for_create(:open, %{subject: "Issue #{i}"})
|> Ash.create!()
if rem(i, 2) == 0 do
ticket
|> Ash.Changeset.for_update(:close)
|> Ash.update!()
else
ticket
end
end
[
%Helpdesk.Support.Ticket{
id: "d2c428d4-d3c6-474a-a353-3ecdaeef3080",
subject: "Issue 0",
status: :closed,
__meta__: #Ecto.Schema.Metadata<:built, "">
},
%Helpdesk.Support.Ticket{
id: "34844252-aeeb-4c4f-9d1b-9526f9ac9813",
subject: "Issue 1",
status: :open,
__meta__: #Ecto.Schema.Metadata<:built, "">
},
%Helpdesk.Support.Ticket{
id: "4dd6b7b4-a3c5-4630-b26f-d85550b53858",
subject: "Issue 2",
status: :closed,
__meta__: #Ecto.Schema.Metadata<:built, "">
},
%Helpdesk.Support.Ticket{
id: "6def5674-8504-4062-a1d6-b5cc1c2c1b06",
subject: "Issue 3",
status: :open,
__meta__: #Ecto.Schema.Metadata<:built, "">
},
%Helpdesk.Support.Ticket{
id: "edc86cc1-0455-41ab-8f6e-2d3b00351bb5",
subject: "Issue 4",
status: :closed,
__meta__: #Ecto.Schema.Metadata<:built, "">
},
%Helpdesk.Support.Ticket{
id: "e537457b-59fa-4d41-bf6f-54ac019ed76c",
subject: "Issue 5",
status: :open,
__meta__: #Ecto.Schema.Metadata<:built, "">
}
]
tickets 에 임의의 리소스 목록이 만들어 졌다. 영속화 되지 않은 데이터이다. 이 데이터를 Ash 를 통해 조회하려면 어떻게 할 수 있는지 알아 보자. 제목에 “2” 를 포함한 리소스만 읽는 쿼리는 다음과 같다.
# Ash.Query는 매크로이므로 require 해야 함
iex> require Ash.Query
Ash.Query
iex> Helpdesk.Support.Ticket |> Ash.Query.filter(contains(subject, "2")) |> Ash.DataLayer.Simple.set_data(tickets) |> Ash.read!()
[
%Helpdesk.Support.Ticket{
id: "4dd6b7b4-a3c5-4630-b26f-d85550b53858",
subject: "Issue 2",
status: :closed,
__meta__: #Ecto.Schema.Metadata<:built, "">
}
]
Ash.read!() 전에 Ash.DataLayer.Simple.set_data(tickets) 를 통해 파이프라인에 tickets 데이터를 제공한 것을 확인할 수 있다. Ash.Query.filter(contains(subject, "2")) 는 일종의 where 절 이라고 볼 수 있다. 예제 코드의 순서는 read 직전에 set_data 를 지정했지만 set_data 부터 하고 이후에 filter 를 해도 결과는 같았다.
다음은 :closed 티켓 중 제목에 “4” 가 포함되지 않은 티켓의 목록을 얻는 코드이다.
Helpdesk.Support.Ticket
|> Ash.Query.filter(status == :closed and not(contains(subject, "4")))
|> Ash.DataLayer.Simple.set_data(tickets)
|> Ash.read!()
다음 글 에서는 데이터 영속화에 대해 알아 본다.