在 Phoenix 中使用 Ecto 获取数据时仅获取特定字段

问题描述 投票:0回答:2

我正在尝试在 Phoenix 的一个 API 调用中返回一些 JSON 数据。我正在获取

Subject
的所有记录并发送它们,但
Ecto
返回一些我不想要的额外字段。

我能做什么:

  • 仅获取特定属性(例如仅
    id
    name
  • 我的回复中没有不必要的字段(例如
    __meta__
    __owner__

这是我的

Controller
:

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

这是我的

View
:

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

这是我的回应:

[
    {
        "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"
        }
    }
]
elixir phoenix-framework ecto
2个回答
15
投票

将您的视图更改为:

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

此外,您还可以通过将控制器更改为以下方式来要求 Ecto 返回字段子集:

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

0
投票

我在

MyApp.Repo
中使用以下宏,它提供了一种可重用的方式来提取特定字段:

defmodule MyApp.Repo do
  use Ecto.Repo,
    otp_app: :my_app,
    adapter: Ecto.Adapters.Postgres
  use Scrivener, page_size: 10

  import Ecto.Query, warn: false, only: [select: 2]
  def pluck(query, fields) when is_atom(fields) do
    pluck(query, [fields])
  end
  def pluck(query, fields) when is_list(fields) do
    query |> select(^fields) |> all |> Enum.map(&Map.take(&1, fields))
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.