我正在尝试构建一个函数,用于在查询中的给定表的字段中搜索术语。
对于像这样的查询
initial_query =
Answer
|> join(:left, [a], q in assoc(a, :question), as: :question)
|> join(:left, [a, q], s in assoc(a, :survey), as: :survey)
Run Code Online (Sandbox Code Playgroud)
我希望能够通过引用的表中进行搜索:question和:survey。
现在,此代码有效:
initial_query
|> or_where(
[question: t], #:question hard coded
fragment(
"CAST(? AS varchar) ILIKE ?",
field(t, ^field),
^"%#{search_term}%"
)
)
Run Code Online (Sandbox Code Playgroud)
但是,我想要一个将命名绑定作为参数的函数,但我找不到方法来做到这一点。
我的尝试:
defp search_field(initial_query, table, field, search_term) do
initial_query
|> or_where(
[{table, t}],
fragment(
"CAST(? AS varchar) ILIKE ?",
field(t, ^field),
^"%#{search_term}%"
)
)
end
Run Code Online (Sandbox Code Playgroud)
给出错误
** (Ecto.Query.CompileError) unbound variable
tin query. If you are attempting to interpolate a value, use ^var expanding macro: Ecto.Query.or_where/3
when called like this:
search_field(initial_query, :question, :text, search_text)
Run Code Online (Sandbox Code Playgroud)
and
defp search_field(initial_query, table, field, search_term) do
initial_query
|> or_where(
[{^table, t}],
fragment(
"CAST(? AS varchar) ILIKE ?",
field(t, ^field),
^"%#{search_term}%"
)
)
end
Run Code Online (Sandbox Code Playgroud)
Gives
** (Ecto.Query.CompileError) binding list should contain only variables or
{as, var}tuples, got: {^table, t} expanding macro: Ecto.Query.or_where/3
Is there a way to use a variable to reference a named binding in an Ecto Query?
所以这个问题的答案似乎是 Ecto 不支持这样做。@maartenvanvliet 解决方案效果很好,但缺点是依赖于内部实现。
我对这个问题的解决方案是search_field使用此处...描述的语法让函数始终在最后连接的表中进行搜索:
# Searches for the `search_term` in the `field` in the last joined table in `initial_query`.
defp search_field(initial_query, field, search_term) do
initial_query
|> or_where(
[..., t],
fragment(
"CAST(? AS varchar) ILIKE ?",
field(t, ^field),
^"%#{search_term}%"
)
)
end
Run Code Online (Sandbox Code Playgroud)
所以这个函数会像这样使用:
Answer
|> join(:left, [a], q in assoc(a, :question), as: :question)
|> search_field(:text, search_text)
|> join(:left, [a, q], s in assoc(a, :survey), as: :survey)
|> search_field(:title, search_text)
Run Code Online (Sandbox Code Playgroud)
在我看来,这仍然很好读,缺点是要求我们能够更改initial_query.
| 归档时间: |
|
| 查看次数: |
1435 次 |
| 最近记录: |