在 Ecto embeds_many 关联中查询

Query in Ecto embeds_many association

正在尝试使用 Ecto embeds_many,并且效果很好,直到我需要查询嵌入式字段中的一些数据。

所以我有一个类似 product 的东西 embeds_many categories

schema "products" do
  field :code, :string, null: false

  embeds_many :categories, Category,
    on_replace: :delete,
    primary_key: {:id, :binary_id, autogenerate: false}
  do
    field :name, :string
  end
end

def create_changeset(%Product{} = product, attrs) do
  product
  |> cast(attrs, [:code])
  |> cast_embed(:categories, with: &attributes_changeset/2)
end

def attributes_changeset(%{} = product_attribute, attrs) do
  product_attribute
  |> cast(attrs, [:id, :name])
end

创建产品后,我在 postgres 中得到了这样的结果 table

id代码分类

1    11     {"{\"id\": \"dress\", \"name\": \"Dress\"},
             "{\"id\": \"shirt\", \"name\": \"Shirt\"}}
2    22     {"{\"id\": \"dress\", \"name\": \"Dress\"}}

所以现在我想查询所有products其中id == "dress",当然我想得到上面的2个结果。

我试过这样的东西: q = from p in Product, where: fragment("? @> ?", p.categories, '{"id": "dress"}') 但将数组转换为整数:operator does not exist: jsonb[] @> integer[] ... WHERE (p0."categories" @> ARRAY[123,34,105,100,34,58,32,34,100,114,101,115,115,34,125])

或者说: q = from p in Product, where: fragment("? @> ?", p.categories, "[{\"id\": \"dress\"}]"),得到malformed array literal: "[{"id": "dress"}]"

我希望是这样的: q = from p in Product, where: fragment("? -> 'id' = ?", p.categories, "rochie") 但完全不确定这是否有效。

因为 categories 在这里是一个 jsonb[],而不是普通的 json,运算符 @> 不会直接使用它。你可以使用 ANY<@ 来做你想做的事:

where: fragment("? <@ ANY(?)", ~s|{"id": "dress"}|, p.categories)

对于类别数组中的每个类别,这将 运行 '{"id": "dress"}' <@ ? 并且 return 如果其中任何一个匹配则为真。

(~s|"a"| 只是 "\"a\"" 的更简洁的写法。)