Ecto查询字符串字段包含其他字符串

Ser*_*pia 1 elixir sql-like ecto

我正在构建一个简单的搜索功能,我想找到字符串字段中包含字符串的所有记录.

这是我尝试过的.

term = "Moby"
MyApp.Book
|> where([p], String.contains?(p, term))
|> order_by(desc: :inserted_at)
Run Code Online (Sandbox Code Playgroud)

这将返回以下书籍:

  • 白鲸记
  • Sandich Moby Lean
  • 我的Mobyand示例

但我得到:

`String.contains?(p, term)` is not a valid query expression
Run Code Online (Sandbox Code Playgroud)

Dog*_*ert 6

您必须使用它String.replace/3来转义%输入(如果它是由最终用户输入),然后like在查询中使用:

|> where([p], like(p.title, ^"%#{String.replace(term, "%", "\\%")}%"))
Run Code Online (Sandbox Code Playgroud)

例:

iex(1)> term = "Foo%Bar"
iex(2)> query = MyApp.Post |> where([p], like(p.title, ^"%#{String.replace(term, "%", "\\%")}%")) |> order_by(desc: :inserted_at)
#Ecto.Query<from p in MyApp.Post, where: like(p.title, ^"%Foo\\%Bar%"),
 order_by: [desc: p.inserted_at]>
iex(3)> Ecto.Adapters.SQL.to_sql(:all, MyApp.Repo, query)
{"SELECT p0.\"id\", p0.\"title\", p0.\"user_id\", p0.\"inserted_at\", p0.\"updated_at\" FROM \"posts\" AS p0 WHERE (p0.\"title\" LIKE $1) ORDER BY p0.\"inserted_at\" DESC",
 ["%Foo\\%Bar%"]}
Run Code Online (Sandbox Code Playgroud)

如果您不进行替换,则类似的术语"a%b""azb"作为%需要转义的匹配或匹配零个或多个字符的任何序列.