Ecto连接查询导致(Poison.EncodeError)无法编码值

时间:2017-04-22 10:50:54

标签: elixir ecto elixir-framework elixir-poison

我有3张桌子:

  1. 类别
  2. 子类
  3. categorySubcategories
  4. 1个类别有0到多个子类别。

    我有这个函数从类别表中获取所有条目,只获取属于id为1的类别的子类别表的条目:

      def getCategories(conn) do
        categories = all Api.Category
        groceryItemSubcategories = from s in Api.Subcategory,
        join: cs in Api.CategorySubcategory, on: cs.c_id == 1,
        select: %{name: s.name, foo: cs.c_id}
        conn
        |> put_resp_content_type("application/json")
        |> send_resp(200, Poison.encode!(%{categories: categories, groceryItemSubcategories: groceryItemSubcategories}))
      end
    

    发出此错误:

    23:10:27.169 [error] #PID<0.339.0> running Api.Router terminated
    Server: localhost:4000 (http)
    Request: GET /categories
    ** (exit) an exception was raised:
        ** (Poison.EncodeError) unable to encode value: {"subcategories", Api.Subcategory}
            (poison) lib/poison/encoder.ex:383: Poison.Encoder.Any.encode/2
            (poison) lib/poison/encoder.ex:227: anonymous fn/4 in Poison.Encoder.Map.encode/3
            (poison) lib/poison/encoder.ex:228: Poison.Encoder.Map."-encode/3-lists^foldl/2-0-"/3
    
            (poison) lib/poison/encoder.ex:228: Poison.Encoder.Map.encode/3
            (poison) lib/poison/encoder.ex:227: anonymous fn/4 in Poison.Encoder.Map.encode/3
            (poison) lib/poison/encoder.ex:228: Poison.Encoder.Map."-encode/3-lists^foldl/2-0-"/3
    
            (poison) lib/poison/encoder.ex:228: Poison.Encoder.Map.encode/3
            (poison) lib/poison.ex:41: Poison.encode!/2
    

    最后的答案是:

      def getCategories(conn) do
        categories = all Api.Category
        groceryItemSubcategories = Api.Repo.all(from s in Api.Subcategory,
        join: cs in Api.CategorySubcategory, on: cs.s_id == s.id,
        join: c in Api.Category, on: c.id == cs.c_id,
        where: c.id == 1,
        select: %{name: s.name, foo: cs.c_id}
        )
        conn
        |> put_resp_content_type("application/json")
        |> send_resp(200, Poison.encode!(%{categories: categories, groceryItemSubcategories: groceryItemSubcategories}))
      end
    

    使错误消失的部分将语句包装在Api.Repo.All()中。 Dogbert真的是那个回答它的人,所以我不想回答这个问题。

1 个答案:

答案 0 :(得分:1)

原始代码存在两个主要问题:

  1. 您忘记在第二个查询中致电Repo.all

  2. 您在查询中选择了一个元组,然后将其编码为JSON。 Poison确实将编码元组处理为JSON。您可以改为选择列表或地图,具体取决于您想要的数据结构。以下是如何选择地图:

    groceryItemSubcategories = Api.Repo.all(from s in Api.Subcategory,
      join: cs in Api.CategorySubcategory, on: cs.s_id == s.id,
      join: c in Api.Category, on: c.id == cs.c_id,
      where: c.id == 1,
      select: %{name: s.name, c_id: cs.c_id})