Ecto join 查询导致 (Poison.EncodeError) 无法对值进行编码
Ecto join query causing (Poison.EncodeError) unable to encode value
我有 3 个 table:
- 类别
- 子类别
- 类别子类别
1 个类别有 0 到多个子类别。
我有这个函数,它获取类别 table 中的所有条目,并且只获取属于 id 为 1 的类别的子类别 table 的条目:
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 确实是回答这个问题的人,所以我不想回答这个问题。
原始代码有两个主要问题:
您忘记在第二个查询中调用 Repo.all
。
您正在 select 查询中的元组,然后将其编码为 JSON。 Poison 确实将编码元组处理为 JSON。您可以 select 列表或映射,具体取决于您想要的数据结构。 select 地图的方法如下:
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})
我有 3 个 table:
- 类别
- 子类别
- 类别子类别
1 个类别有 0 到多个子类别。
我有这个函数,它获取类别 table 中的所有条目,并且只获取属于 id 为 1 的类别的子类别 table 的条目:
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 确实是回答这个问题的人,所以我不想回答这个问题。
原始代码有两个主要问题:
您忘记在第二个查询中调用
Repo.all
。您正在 select 查询中的元组,然后将其编码为 JSON。 Poison 确实将编码元组处理为 JSON。您可以 select 列表或映射,具体取决于您想要的数据结构。 select 地图的方法如下:
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})