Elixir 在“中调用我自己的谓词”;其中;外胚层

Elixir 在“中调用我自己的谓词”;其中;外胚层,elixir,ecto,Elixir,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 如何修复它?我认为这是不可能的 作为一种方法,您可以创建一个单独的策略模块,该

我希望能够调用一个函数或我的谓词(在“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

如何修复它?

我认为这是不可能的

作为一种方法,您可以创建一个单独的策略模块,该模块实现在记录上或作为查询的一部分处理它的功能:

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
defmodule-CheapItemPolicy-do
别名exto.Query
仅导入查询:[其中:3]
def是否便宜?(%Item{price:price})是否便宜
价格以100..200为单位
结束
def是否便宜?(%Query{}=Query)do
查询
|>式中([q],q.price>=100)

|>其中([q],q.price当然可以,但是不能使用函数

例如:

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")

但宏结果仍然需要是有效的查询AST,所以没有什么花哨的东西可以到达那里。

卢卡斯的答案就是您所需要的。EXTO查询是在编译时生成的,所以如果您想使用某些东西作为谓词,就需要宏

但我想建议您也可以编写您的查询。这应该会让您产生以下想法:

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)
基本上,使用可组合函数逐点构建查询


另外,我总是使用“查询”表单进行外部查询。你也可以使用“管道”通过将查询管道化到函数中来形成和组合查询。

这是不可能的。当您有这样一个查询时,它需要转换为您的数据库查询语言。如果您开始在其中编写任意代码,则ecto将无法进行转换。如果您向我们提供您要运行的谓词和使用的DB的示例。为什么使用宏?我如何使用我自己的不需要片段的谓词?@Bingi您仍然需要使用宏作为
,其中
也是构建
exto的宏。查询
结构和所需的AST。无法调用列数据上的函数,因为它需要使用exto来传输将该功能代码指定给DB查询。Ecto查询中的所有内容都需要预先计算并作为原始数据发送到DB,或者需要可翻译才能进行查询。您不需要使用
片段
,但通常情况下,当您需要Ecto宏时会出现这种情况。不过,您可以在那里自由编写任何可以在查询中使用的代码,否则就不需要了不可能。我怎么能使用我自己的谓词,它不需要片段?@Bingi在这种情况下,这是不可能的,因为我上面给出的原因。告诉我我需要什么,没有你我不知道。对不起,我不明白你的意思。你需要一个更具体的例子吗?
query = from r in MySchema, where: r.another_column == ^another_value

query |> my_predicate(some_value)