如何在 Ecto 中执行“model.field 包含数组的位置”?

G4b*_*i3l 4 arrays elixir ecto phoenix-framework

假设我有一个模型,它的字段sizes是一个数组(例如sizes: ['S', 'M', 'L'])。我想要完成的是构建 API,让用户能够根据大小过滤这些模型。所以GET对这条路径的请求:

.../products?sizes=['S','M']

应该返回给定数组是其sizes字段子数组的所有产品。所以我不想也不需要完全匹配,但我希望用户能够按照上面的解释进行过滤。我将如何在我的 Phoenix API 中实现这一点?

我只能完成过滤包含特定值 ( where: this in that) 的那些,但是如果我传入一个数组并且我想检查该数组是否包含在该模型字段中,我有点迷茫。

在此先感谢您的帮助,如果您需要任何其他信息,请告诉我。

编辑

我正在尝试使用fragment("? @> ?::varchar[]", p.sizes, ^params["sizes'] )并且它可以工作,但是如果我[color: "red"]在现有过滤器的顶部添加任何简单的过滤器,它就会失败,这意味着我无法创建一组过滤器,然后将其添加到where子句中,例如... and ^filters

filters = Ecto.Changeset.cast(%Product{}, params, [], [:color])
  |> Map.fetch!(:changes)
  |> Map.to_list

# Do I need to actually do this check like this ? (It fails otherwise)
sizes = if is_nil(params["sizes"]) do [] else params["sizes"] end

products_query = from(
  p in Product,
  where: fragment("? @> ?::varchar[]", p.sizes, ^sizes) and
         ^filters
)
Run Code Online (Sandbox Code Playgroud)

这目前不起作用。

Dog*_*ert 6

正如您已经发现的那样,您需要将@>withfragment用于“数组包含数组”操作。对于您的第二个问题,要使用 链接where表达式and,您只需添加另一个where

products_query = from(
  p in Product,
  where: fragment("? @> ?::varchar[]", p.sizes, ^sizes),
  where: ^filters
)
Run Code Online (Sandbox Code Playgroud)