Ecto - 如何按准确顺序按 ID 获取记录
Ecto - how to get records by ids in exact order
我有一个记录 ID 列表 - [9, 1, 4, 3]
。
我想从 postgresql 中检索记录并希望它们按此 ID 列表中的顺序排序。但是当我进行查询时,记录以任意顺序返回:
Ecto.Query.from(r in Record, where: r.id in [9, 1, 4, 3])
|> Repo.all()
|> Enum.map(&Map.get(&1, :id)) # => [4, 9, 1, 3]
如何检索具有相同顺序的记录?
我认为在数据库中没有任何简单的方法可以做到这一点,但在 Elixir 中有一种方法可以做到这一点:
ids = [123, 4, 1, 3, 2, 456]
posts = from(p in Post, where: p.id in ^ids, select: {p.id, p}) |> Repo.all |> Map.new
posts = for id <- ids, posts[id], do: posts[id]
posts |> Enum.map(&(&1.id)) |> IO.inspect
输出:
[4, 1, 3, 2]
首先,我们构建id => post
的地图。然后,对于 ids
中的每个 id,如果找到,我们将得到相应的 Post。在我的应用程序中,没有 ID 为 123 或 456 的 Post,因此它们在 for
.
中被忽略了
你可以使用PostgreSQL的array_position
function and Ecto's fragment function。在您的情况下,它看起来像:
Ecto.Query.from(r in Record, where: r.id in [9, 1, 4, 3])
|> Ecto.Query.order_by([r], fragment("array_position(?, ?)", [9, 1, 4, 3], r.id)
|> Repo.all()
我会避免在数据库引擎之外处理数据。在这个简单的例子中应该无关紧要。但是,它可能会影响更大的数据集或更复杂的数据结构的性能,因为首先,您必须将结果加载到内存中,然后对它们执行操作以更改顺序。
我有一个记录 ID 列表 - [9, 1, 4, 3]
。
我想从 postgresql 中检索记录并希望它们按此 ID 列表中的顺序排序。但是当我进行查询时,记录以任意顺序返回:
Ecto.Query.from(r in Record, where: r.id in [9, 1, 4, 3])
|> Repo.all()
|> Enum.map(&Map.get(&1, :id)) # => [4, 9, 1, 3]
如何检索具有相同顺序的记录?
我认为在数据库中没有任何简单的方法可以做到这一点,但在 Elixir 中有一种方法可以做到这一点:
ids = [123, 4, 1, 3, 2, 456]
posts = from(p in Post, where: p.id in ^ids, select: {p.id, p}) |> Repo.all |> Map.new
posts = for id <- ids, posts[id], do: posts[id]
posts |> Enum.map(&(&1.id)) |> IO.inspect
输出:
[4, 1, 3, 2]
首先,我们构建id => post
的地图。然后,对于 ids
中的每个 id,如果找到,我们将得到相应的 Post。在我的应用程序中,没有 ID 为 123 或 456 的 Post,因此它们在 for
.
你可以使用PostgreSQL的array_position
function and Ecto's fragment function。在您的情况下,它看起来像:
Ecto.Query.from(r in Record, where: r.id in [9, 1, 4, 3])
|> Ecto.Query.order_by([r], fragment("array_position(?, ?)", [9, 1, 4, 3], r.id)
|> Repo.all()
我会避免在数据库引擎之外处理数据。在这个简单的例子中应该无关紧要。但是,它可能会影响更大的数据集或更复杂的数据结构的性能,因为首先,您必须将结果加载到内存中,然后对它们执行操作以更改顺序。