2017-10-04 18 views
0

我希望能够调用一个函数或我在Ecto的“where”中的谓词。我想这样的:在Ecto的“where”中调用我自己的谓词

items = where(Item, [x], Item.my_predicate?(x)) 

# items = where(Item, [x], Item.my_predicate?(x) == true) 

它抛出一个异常:

`Item.my_predicate?(x)` is not a valid query expression 

如何解决呢?

+0

这是不可能的。当你有这样的查询时,它需要翻译成你的数据库查询语言。如果您开始在其中编写任意代码,ecto将无法进行该翻译。 –

+0

如果您向我们提供您想要运行的谓词和您使用的数据库的示例,那么向您提供更多帮助会更容易。 – Hauleth

回答

0

但是,当然可以使用功能but macros

例子:

defmodule Foo do 
    defmacro concat_ws(joiner, columns) do 
    params_list = "?" |> List.duplicate(Enum.count(columns)) |> Enum.join(",") 

    quote do 
     fragment(unquote("concat_ws(?," <> params_list <>")", joiner, unquote_splicing(columns)) 
    end 
    end 
end 

items = where(Item, [x], Foo.concat_ws(" ", [x.a, x.b]) == "a b") 

例无fragment

defmodule Foo do 
    defmacro eql(a, b) do 
    quote do: not (is_nil(a) or is_nil(b)) and a == b 
    end 
end 

但还是宏观的结果必须是有效的查询AST,所以没有什么花哨可以在那里着陆。

+0

为什么宏?我如何使用我自己的不需要片段的谓词? – Bingi

+0

@Bingi仍然需要使用宏作为'where'也是宏,它用所需的AST构建'Ecto.Query'结构。没有办法对列数据调用函数,因为它需要Ecto将该函数代码转换为数据库查询。 Ecto查询中的所有内容都需要预先计算并作为原始数据发送到数据库,或者需要被翻译为查询。您不需要使用'fragment',但通常情况下,您需要使用Ecto宏。但是,您可以自由地编写任何可用于查询的代码,否则这是不可能的。 – Hauleth

+0

如何使用我自己的不需要片段的谓词? – Bingi

0

我不认为这是可能的。

正如一条路可走,你可以创建一个实现函数来处理其上的记录或作为查询的一部分单独的策略模块:

defmodule CheapItemPolicy do 
    alias Ecto.Query 
    import Query, only: [where: 3] 

    def is_cheap?(%Item{price: price}) do 
    price in 100..200 
    end 

    def is_cheap?(%Query{} = query) do 
    query 
    |> where([q], q.price >= 100) 
    |> where([q], q.price <= 200) 
    end 
end 

显然,这只是一条路可走。你可以把所有这些函数放到已经存在的模块中,或者把它们分解成不同的模块或者用相同的逻辑创建一个数据库函数,或者处理应用程序级别的检查或者其他任何事情

0

Lukasz的答案是你所需要的。 Ecto查询是在编译时建立的,所以如果你想使用某些谓词的话,你需要宏。

但我想建议你也可以撰写你的查询。这应该给你的想法:

def my_predicate(query, value) do 
    from r in query, where: r.some_column == ^value 
end 

而且使用它像:由位

query = from r in MySchema, where: r.another_column == ^another_value 

query |> my_predicate(some_value) 

基本上,构建查询一下,使用组合的功能。

PS。我总是使用Ecto查询的“查询”表单。您还可以使用“管道”形式并通过管道查询功能编写查询。

+0

告诉我我需要什么,没有你我不知道。 – Bingi

+0

对不起,我不明白你的意思。你需要一个更具体的例子? – vfsoraki