Postgresql 在Elixir with Postgres中,如何让数据库返回未使用的枚举值?
我有一个外种名。博士后:Postgresql 在Elixir with Postgres中,如何让数据库返回未使用的枚举值?,postgresql,enums,elixir,ecto,processing-efficiency,Postgresql,Enums,Elixir,Ecto,Processing Efficiency,我有一个外种名。博士后: # @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, d
# @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
这是可行的,但我相信如果我们只是向数据库询问这些信息,这可能会更有效率
你知道怎么做吗?如果你想得到所有使用过的枚举的列表,你只需要在货币字段上做一个区分。这将使用Postgres DISTINCT ON运算符:
from(c in Currency,
distinct: c.currency,
select: c.currency
)
这将查询表(按货币列唯一),并仅返回货币列值。您应该获得表中存在的所有枚举的数组
这样做有一些效率问题,可以通过物化视图、查找表、内存缓存等来缓解。但是,如果您的数据集不是非常大,您应该可以使用它一段时间
编辑:
根据响应,我将展示如何获取未使用的枚举
有两种方法可以做到这一点
纯SQL
此查询将获取所有已使用的枚举,并与整个可用枚举集有所不同。我们用于执行此操作的运算符是EXCEPT,您可以获得具有enum_范围的所有可用枚举的列表。我将使用unnest将枚举类型数组转换为单独的行:
选择unnestenum_rangeNULL::currency作为未使用的_枚举
除了
在c.name上选择DISTINCT c.name
从货币c
通过执行以下操作,可以在EXTO中执行此原始SQL:
Ecto.Adapters.SQL.query!(MyApp.Repo, "SELECT unnest(...", [])
从中您将得到一个Postgresx。结果是您必须从中获取值:
result
|> Map.get(:rows, [])
|> List.flatten()
|> Enum.map(&String.to_existing_atom/1)
我真的不确定有什么方法可以用纯EXTO来编写这个查询,但是如果你明白了,请告诉我
编码
您可以使用distinct执行我之前发布的第一个查询,然后在代码中执行差异
query = from(c in Currency,
distinct: c.currency,
select: c.currency
)
CurrencyEnum.__enums__() -- Repo.all(query)
就性能而言,任何一种方法都可能可以忽略不计,因此这取决于您。是否应在调用中使用distinct:true选项进行选择?另外,我也不知道如何查询数据库中缺少的信息。我对distinct:true一无所知,因此我无法评论是否需要使用它。数据库包含一组完整的枚举。它还包含一个表,可以使用这些值,也可以不使用这些值。这样做的目的是获取表中使用的值,然后只返回那些未包含在表中收集的值中的枚举。为响应干杯!对不起,我的问题有点模棱两可。实际上,我希望数据库返回未使用的枚举,即非活动值