在Ecto embeds_many关联中查询

时间:2017-10-23 12:32:17

标签: postgresql elixir ecto jsonb

尝试使用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表中最终得到类似的内容

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")但是根本不确定是否有效。

1 个答案:

答案 0 :(得分:2)

由于此处categoriesjsonb[],而不是普通json,因此运营商@>无法直接使用它。您可以使用ANY<@来执行您想要的操作:

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

这将为categories数组中的每个类别运行'{"id": "dress"}' <@ ?,如果其中任何一个匹配,则返回true。

~s|"a"|只是一种更清晰的写作方式"\"a\""。)