尝试使用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")
但是根本不确定是否有效。
答案 0 :(得分:2)
由于此处categories
是jsonb[]
,而不是普通json
,因此运营商@>
无法直接使用它。您可以使用ANY
和<@
来执行您想要的操作:
where: fragment("? <@ ANY(?)", ~s|{"id": "dress"}|, p.categories)
这将为categories数组中的每个类别运行'{"id": "dress"}' <@ ?
,如果其中任何一个匹配,则返回true。
(~s|"a"|
只是一种更清晰的写作方式"\"a\""
。)