You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ecto中实现同时支持binary_id或字符串参数的查询

Ecto binary_id合法性判断

不需要正则校验,直接使用Ecto内置的类型能力即可实现校验:

  • 如果你使用Ecto默认的UUID类型作为binary_id,直接调用Ecto.UUID.dump/1即可:返回{:ok, _}说明是合法binary_id,返回:error则为不合法。
    示例代码:
    defp valid_binary_id?(str) when is_binary(str) do
      match?({:ok, _}, Ecto.UUID.dump(str))
    end
    
  • 如果你使用自定义类型作为binary_id,可以通过Schema的字段定义获取类型后调用Ecto.Type.cast/2校验:
    示例代码:
    @user_id_type Ecto.Schema.__field__(MyProject.Accounts.User, :id).type
    
    defp valid_binary_id?(str) when is_binary(str) do
      match?({:ok, _}, Ecto.Type.cast(@user_id_type, str))
    end
    
优雅的多条件查询实现

你不需要编写两份完全重复的查询逻辑,可以通过动态拼接查询条件实现需求,避免非合法binary_id和id字段比较触发CastError:

import Ecto.Query

def get_user(id_or_username) do
  match_conditions =
    if valid_binary_id?(id_or_username) do
      dynamic([u], u.id == ^id_or_username or u.username == ^id_or_username)
    else
      dynamic([u], u.username == ^id_or_username)
    end

  MyProject.Accounts.User
  |> where([u], is_nil(u.deleted_at))
  |> where(^match_conditions)
  |> MyProject.Repo.one()
end
原报错原因说明

Ecto在查询构建阶段就会对参数做类型校验,你将非合法binary_id的字符串和UUID类型的id字段做等值比较时,Ecto会提前尝试转换参数类型,转换失败就会直接抛出CastError,不会等到查询实际执行。因此只需要在构建查询时,判断入参类型后再决定是否加入id匹配条件即可。

内容的提问来源于stack exchange,提问作者Freedom_Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:21:00