提问人:IvonaK 提问时间:11/15/2023 更新时间:11/16/2023 访问量:47
在 Elixir 中为 Ecto 的 Repo.preload 添加限制选项
Adding a Limit Option to Ecto's Repo.preload in Elixir
问:
我在 Elixir 中有一个使用 Ecto 的函数,可以预加载给定实体的关联。当前实现如下所示:
@spec get(integer() | String.t(), list()) :: t() | nil
def get(id, preloads \\ []) do
Shop
|> Repo.get(id)
|> Repo.preload(preloads)
end
我是这样使用它的:
Shop.get(id, [
:coustomers,
:products
])
有没有可能让它变成这样?
Shop.get(id, [
:coustomers,
{:limit,:products,3}
])
答:
0赞
zwippie
11/16/2023
#1
可以限制预加载记录的数量,但它需要不止一个行,并且可能不像您希望或期望的那样灵活:
products_query = from p in Product, limit: 3, order_by: p.inserted_at
Shop
|> Repo.get(id)
|> Repo.preload([products: products_query])
也许你可以创建一个函数,它接受一个模块和一个数字(用于限制)并返回与上述内容相同的内容,例如:products_query
def preload_query(module, limit) do
from a in module, limit: ^limit
end
并以此作为以下参数:Shop.get/2
Shop.get(id, [:customers, products: preload_query(Product, 3)])
评论
0赞
Peaceful James
11/16/2023
文档说“预加载查询中的限制和偏移等操作将影响整个结果集,而不是每个关联”。hexdocs.pm/ecto/Ecto.Query.html#preload/3
0赞
zwippie
11/16/2023
是的,使用预加载时有很多陷阱。对于这个(简单的)案例,我认为这并不重要?
0赞
Peaceful James
11/16/2023
我认为这确实很重要。由于您的子查询在shop_id上没有,因此您将列出属于任何商店的 3 个最近插入的产品。where
1赞
zwippie
11/16/2023
啊,但这是,不是.:)它只会返回与给定商店关联的记录,所以这很好。并且还对预加载的关联运行单独的查询,因为我们只想对它们进行简单的限制,这应该也可以。只是为了确定,刚刚通过一些测试确认了它。为简洁起见,我的答案是使用 just 而不是 updated。Repo.preload
Query.preload
Repo.preload
preload
Repo.preload
0赞
Peaceful James
11/16/2023
你是对的。我的脑海里只是删掉了你回答的部分。对不起。Repo.
0赞
Peaceful James
11/16/2023
#2
我会做这样的事情:
defmodule Shops do
def get_shop(nil), do: nil
def get_shop(shop_id) do
limited_products =
Product
|> where(shop_id: ^shop_id)
|> limit(3)
Shop
|> from(as: :shop)
|> join(:inner, [shop: shop], product in subquery(limited_products), on: true, as: :products)
|> select([shop: shop, products: products], %{shop | products: products})
|> Repo.one()
end
end
我还没有测试过这个。它只是为了照明。
评论
join
where product.some_index < 3
some_index