gpt4 book ai didi

postgresql - 在带有 Postgres 的 Elixir 中,我怎样才能让数据库返回未使用的枚举值?

转载 作者:行者123 更新时间:2023-11-29 13:08:50 24 4
gpt4 key购买 nike

我有一个 EctoEnum.Postgres:

# @see: https://en.wikipedia.org/wiki/ISO_4217
defmodule PricingEngine.Pricing.CurrencyEnum do
@options [
:AED,
:AFN,
# snip...
:ZWL
]
use EctoEnum.Postgres,
type: :currency,
enums: @options

def values, do: @options
end

此枚举已包含在我们的 Postgres 数据库中

我们还有一个结构:

defmodule PricingEngine.Pricing.Currency do
use Ecto.Schema
import Ecto.Changeset

schema "currencies" do
field(:currency, PricingEngine.Pricing.CurrencyEnum)

timestamps()
end

@doc false
def changeset(currency, attrs) do
currency
|> cast(attrs, [:currency])
|> validate_required([:currency])
|> unique_constraint(:currency)
end
end

我们目前可以成功地使用以下函数来确定哪些货币是活跃/使用的:

  def active_currency_isos do
Repo.all(select(Currency, [record], record.currency))
end

defdelegate all_currency_isos,
to: CurrencyEnum,
as: :values

def inactive_currency_iso do
Pricing.all_currency_isos() -- Pricing.active_currency_isos()
end

这行得通,但我相信如果我们只向数据库询问此信息,效率会更高。

知道怎么做吗?

最佳答案

如果你想获得所有使用过的枚举的列表,你应该在货币字段上做一个distinct。这使用了 Postgres DISTINCT ON 运算符:

from(c in Currency,
distinct: c.currency,
select: c.currency
)

这将查询货币列唯一的表,并仅返回货币列值。您应该获得表中存在的所有枚举的数组。

以这种方式进行时存在一些效率问题,这可以通过物化 View 、查找表、内存缓存等来缓解。但是,如果您的数据集不是非常大,您应该能够将其用于一会儿。

编辑:

根据响应,我将展示如何获取未使用的枚举。

有两种方法可以做到这一点。

纯SQL

此查询将获取所有使用过的枚举,并与整个可用枚举集有所不同。我们用来执行此操作的运算符是 EXCEPT,您可以使用 enum_range 获取所有可用枚举的列表。我将使用 unnest 将枚举类型的数组转换为单独的行:

SELECT unnest(enum_range(NULL::currency)) AS unused_enums
EXCEPT (
SELECT DISTINCT ON (c.name) c.name
FROM currencies c
)

您可以通过执行以下操作在 Ecto 中执行此原始 SQL:

Ecto.Adapters.SQL.query!(MyApp.Repo, "SELECT unnest(...", [])

由此您将获得一个 Postgresx.Result,您必须从中获取值:

result
|> Map.get(:rows, [])
|> List.flatten()
|> Enum.map(&String.to_existing_atom/1)

我不太确定用纯 Ecto 编写这个查询的方法,但如果你想出来了请告诉我。

在代码中

您可以使用 distinct 执行我之前发布的第一个查询,然后在代码中执行不同的操作。

query = from(c in Currency,
distinct: c.currency,
select: c.currency
)

CurrencyEnum.__enums__() -- Repo.all(query)

任何一种方式在性能方面都可能微不足道,所以这取决于您。

关于postgresql - 在带有 Postgres 的 Elixir 中,我怎样才能让数据库返回未使用的枚举值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57587518/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com