是否可以使用 Ecto.Query 生成一个组合来自多个数据库列的数据的查询子句?

问题描述 投票:0回答:1

我有一个简单的 Postgres 表,用于存储

first_name
last_name
记录。假设它包含以下示例数据:

名字约翰简鲍勃马克约翰
姓氏
史密斯
母鹿
史密斯
约翰逊
韦恩
我还有以下函数来搜索给定搜索字符串的记录
Person

name

该函数按预期工作,因为如果您搜索 
def search_persons_by_name(name) do query = "%#{name}%" Person |> where([p], ilike(p.first_name, ^query)) |> or_where([p], ilike(p.last_name, ^query)) |> Repo.all end

,它将检查是否有任何记录的

name
first_name
匹配,并相应地返回记录。例如,使用搜索字符串
last_name
,该函数将返回“John Smith”和“John Wayne”的记录对象。
我要解决的限制是,如果 

"john"

给出为

name
,它不会返回“John Smith”的记录,而是会生成一个空列表。我尝试像这样修改查询:
"john smith"

但这甚至无法编译,并给出错误:
def search_persons_by_name(name) do query = "%#{name}%" Person |> where([p], ilike(p.first_name, ^query)) |> or_where([p], ilike(p.last_name, ^query)) |> or_where([p], ilike("#{p.first_name} #{p.last_name}", ^query)) |> Repo.all end

我通过执行以下操作取得了部分成功:

** (Ecto.Query.CompileError) \`"#{wp.first_name} #{p.last_name}"` is not a valid query expression. Only literal binaries and strings are allowed, dynamic values need to be explicitly interpolated in queries with ^

但这里的问题是,如果不使用 
def search_persons_by_name(name) do all_names = String.split(name, " ", trim: true) Person |> where([p], p.first_name in ^all_names or p.last_name in ^all_names) |> Repo.all end

,搜索字符串

ilike
现在必须区分大小写,这也是不理想的。
然后我尝试在查询中添加一个 

name

子句,例如:

select

但这也无法编译并出现错误
def search_persons_by_name(name) do all_names = String.split(name, " ", trim: true) |> Enum.each(fn s -> String.downcase(s) end) Person |> select([p.first_name |> String.downcase |> selected_as(:first_name_lower)]) # only first_name just to try |> where([p], selected_as(:first_name_lower) in ^all_names) |> Repo.all end

我收集到的是,在 

** (Ecto.Query.CompileError) `String.downcase(p.first_name)` is not a valid query expression.

ilike
中搜索的字符串不能由 elixir 函数操作,因为这样做会导致编译错误。
所以我需要一些帮助来实现这一目标。

elixir ecto
1个回答
0
投票

select

具体是通过发送 SQL“
fragment

”并绕过 Ecto。这允许在与其他值进行任何比较之前转换列值。

© www.soinside.com 2019 - 2024. All rights reserved.