phi*_*hil 4 elixir ecto phoenix-framework
我从客户端传入的参数列表中创建了一个查询列表:
[
#Ecto.Query<from v in Video, where: v.brand == ^"Cocacola">,
#Ecto.Query<from v in Video, where: v.type == ^"can">
]
Run Code Online (Sandbox Code Playgroud)
但是,我需要遍历此列表并编写一个查询,该查询是所有查询的累加......(下一个查询的输入是当前查询等。)
有人能指出我如何做到这一点的正确方向。这将不胜感激!
我知道我可以一一撰写查询。但是我从客户端获取参数并且有一长串字段(品牌、类型等),并且不想对每个字段进行单独的查询。
除非您打开单个查询结构并检查它们的底层实现,否则既不可能也不建议像这样在 Ecto 中连接查询。相反,您应该尝试将它们分解并使其可组合。
Ecto 使您可以非常轻松地将查询组合在一起:
defmodule VideoQueries do
import Ecto.Query
def with_brand(query, brand) do
where(query, [v], v.brand == ^brand)
end
def with_type(query, type) do
where(query, [v], v.type == ^type)
end
def latest_first(query) do
order_by(query, desc: :inserted_at)
end
end
Run Code Online (Sandbox Code Playgroud)
你可以这样称呼它们:
Video
|> VideoQueries.with_brand("Cocacola")
|> VideoQueries.with_type("can")
|> VideoQueries.latest_first
Run Code Online (Sandbox Code Playgroud)
现在假设您获得了一个Map或Keyword List多个查询参数并且想要应用它们,您仍然可以通过在运行时迭代键/值来将它们一起调用。您可以构建一个为您执行此操作的过滤器方法:
# Assuming args are a Keyword List or a Map with Atom keys
def filter(query, args) do
Enum.reduce(args, query, fn {k, v}, query ->
case k do
:brand -> with_brand(query, v)
:type -> with_type(query, v)
_ -> query
end
end)
end
Run Code Online (Sandbox Code Playgroud)
并且可以动态组合这样的查询:
user_input = %{brand: "Cocacola", type: "can"}
Video
|> VideoQueries.filter(user_input)
|> Repo.all
Run Code Online (Sandbox Code Playgroud)
进一步阅读: