我有一个简单的 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 函数操作,因为这样做会导致编译错误。所以我需要一些帮助来实现这一目标。