elixirphoenix-frameworkecto

Get only specific fields when fetching data using Ecto in Phoenix


I'm trying to return some JSON Data in one of my API Calls in Phoenix. I'm fetching all records of Subject and sending them but Ecto returns some extra fields that I do not want.

What can I do to:


This is my Controller:

# Controller
def index(conn, _) do
    subjects = Subject |> Repo.all
    conn |> render subjects: subjects
end

This is my View:

# View
def render("index.json", %{subjects: subjects}) do
    subjects
end

This is my response:

[
    {
        "teachers": {
            "__owner__": "Elixir.MyApp.Subject",
            "__field__": "teachers",
            "__cardinality__": "many"
        },
        "updated_at": "2015-06-20T15:32:20Z",
        "topics": {
            "__owner__": "Elixir.MyApp.Subject",
            "__field__": "topics",
            "__cardinality__": "many"
        },
        "name": "Physics",
        "inserted_at": "2015-06-20T15:32:20Z",
        "id": 1,
        "__meta__": {
            "state": "loaded",
            "source": "subjects"
        }
    },
    {
        "teachers": {
            "__owner__": "Elixir.MyApp.Subject",
            "__field__": "teachers",
            "__cardinality__": "many"
        },
        "updated_at": "2015-06-20T15:37:59Z",
        "topics": {
            "__owner__": "Elixir.MyApp.Subject",
            "__field__": "topics",
            "__cardinality__": "many"
        },
        "name": "Chemistry",
        "inserted_at": "2015-06-20T15:37:59Z",
        "id": 2,
        "__meta__": {
            "state": "loaded",
            "source": "subjects"
        }
    },
    {
        "teachers": {
            "__owner__": "Elixir.MyApp.Subject",
            "__field__": "teachers",
            "__cardinality__": "many"
        },
        "updated_at": "2015-06-20T15:38:41Z",
        "topics": {
            "__owner__": "Elixir.MyApp.Subject",
            "__field__": "topics",
            "__cardinality__": "many"
        },
        "name": "Mathematics",
        "inserted_at": "2015-06-20T15:38:41Z",
        "id": 3,
        "__meta__": {
            "state": "loaded",
            "source": "subjects"
        }
    },
    {
        "teachers": {
            "__owner__": "Elixir.MyApp.Subject",
            "__field__": "teachers",
            "__cardinality__": "many"
        },
        "updated_at": "2015-06-22T15:40:17Z",
        "topics": {
            "__owner__": "Elixir.MyApp.Subject",
            "__field__": "topics",
            "__cardinality__": "many"
        },
        "name": "Biology",
        "inserted_at": "2015-06-22T15:40:17Z",
        "id": 4,
        "__meta__": {
            "state": "loaded",
            "source": "subjects"
        }
    }
]

Solution

  • Change your view to:

    def render("index.json", %{subjects: subjects}) do
      Enum.map(subjects, &Map.take(&1, [:id, :name]))
    end
    

    Additionally, you can also ask Ecto to return a subset of fields by changing your controller to:

    def index(conn, _) do
      subjects = from(s in Subject, select: %{id: s.id, name: s.name}) |> Repo.all
      conn |> render subjects: subjects
    end