# 【Elixir】EctoでSELECT句のクエリを柔軟に扱う：select_merge関数の効果的な使い方
> ElixirのEctoライブラリの`select_merge/3`関数を使ったクエリの動的な構築方法を、具体例を交えて詳しく解説します。
- Canonical: https://c-a-p-engineer.github.io/elixir-ecto-select-merge/
- Published: 2024-05-01T11:00:00.000Z
- Modified: 2024-05-01T11:00:00.000Z
- Categories: Elixir
- Tags: Elixir

ElixirのEctoライブラリの`select_merge/3`関数を使ったクエリの動的な構築方法を、具体例を交えて詳しく解説します。動的クエリがアプリケーションの柔軟性をどのように向上させるかを学び、実用的な利用シナリオを掘り下げます。

## select_mergeの基本
`select_merge/3`は、Ectoクエリにおいて、すでに定義された`select`ステートメントに条件を動的に追加するために使用します。この関数は、クエリの柔軟性を大きく向上させるため、動的なレポート生成やユーザーの入力に基づいて結果を変更する必要がある場合にとくに有用です。

### サンプルコード

以下の例では、`users`テーブルからデータを取得する基本的なEctoクエリを作成し、特定のフィールドを動的に選択する方法を示します。

まずはスキーマを定義。

```elixir
# モジュールとスキーマの定義
defmodule MyApp.User do
  use Ecto.Schema

  schema "users" do
    field :name, :string
    field :age, :integer
    field :email, :string
  end
end
```

次にクエリを定義します。

```
# クエリ関数の定義
defmodule MyApp.UserQuery do
  import Ecto.Query
  alias MyApp.User
  alias MyApp.Repo

  # 動的にフィールドを選択する関数
  def dynamic_select(fields) do
    base_query = from u in User
    fields_query = Enum.reduce(fields, base_query, fn field, query ->
      select_merge(query, [u], %{^field => field(u, ^field)})
    end)

    Repo.all(fields_query)
  end
end
```

このコードでは、まずユーザーのスキーマを定義し、その後`dynamic_select`関数を用いてフィールドを動的に選択しています。この関数は、フィールドのリストを引数として受け取り、それを`select_merge`を用いてクエリに追加しています。

実際に使う場合はこのように出力列のキーワードリストを渡して実行すればOKです。

```elixir
fields = [:name, :email]
MyApp.UserQuery.dynamic_select(fields)
```

こうすることで必要な列だけに絞ったりして高速化を図ったり必要なデータを取ってきたりすることが可能です。

## 参考

- <a href="https://hexdocs.pm/ecto/3.11.2/Ecto.Query.html#select_merge/3" target="_blank" rel="nofollow noopener">Ecto.Query - select_merge/3</a>
