在 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\""
的更简洁的写法。)
正在尝试使用 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\""
的更简洁的写法。)