Prisma 返回 Decimal 类型为字符串?两种解决方法!
2024-10-05 12:37:35
在使用 Prisma 操作数据库时,你可能会碰到 Decimal
类型字段的值以字符串形式返回的情况。例如,你的 aikon_articulo
模型中的 aik_ar_cosnet
字段,数据库中明明存储的是数值 109457.00,Prisma 却返回了字符串 "109457"。这显然与我们期望的结果不符,我们希望 Prisma 返回的值与数据库中的值保持一致。
这个问题的根源在于 Prisma 底层使用了 decimal.js 库来处理 Decimal
类型。decimal.js 是一个专门用于高精度十进制运算的 JavaScript 库,它默认会将数值转换为字符串表示,目的是为了避免 JavaScript 中浮点数精度丢失的问题。
那么,我们该如何让 Prisma 返回数值而不是字符串呢?
一个直接的解决方法是在查询结果上进行转换。你可以遍历查询结果,将字符串类型的 Decimal
字段转换为数值类型。比如,你可以使用 parseFloat()
或 Number()
函数将字符串转换为浮点数。
const articulos = await prisma.aikon_articulo.findMany();
articulos.forEach(articulo => {
articulo.aik_ar_cosnet = parseFloat(articulo.aik_ar_cosnet);
// 或者 articulo.aik_ar_cosnet = Number(articulo.aik_ar_cosnet);
});
这种方法虽然能够解决问题,但略显麻烦,尤其是在需要处理多个 Decimal
字段的时候。
有没有更优雅的解决方案呢?答案是肯定的。我们可以利用 Prisma 的类型转换功能。具体来说,你可以在 Prisma schema 中定义自定义类型,并在其中指定 Decimal
字段的类型为 number
。
model aikon_articulo {
// ... 其他字段 ...
aik_ar_cosnet Decimal @db.Decimal(15,2) @map("aik_ar_cosnet_numeric")
}
type MyDecimal {
aik_ar_cosnet_numeric: number
}
通过 @map
属性,我们将数据库中的 aik_ar_cosnet
字段映射到自定义类型 MyDecimal
的 aik_ar_cosnet_numeric
字段,并将类型指定为 number
。如此一来,Prisma 就会自动将字符串类型的 aik_ar_cosnet
转换为数值类型的 aik_ar_cosnet_numeric
。
你可能会问,用 Decimal
类型表示货币值是否合适?答案是肯定的。Decimal
类型能够精确地表示十进制数值,避免了浮点数精度丢失带来的问题,这在处理货币计算时至关重要。
当然,你也可以考虑使用 BigInt
类型来表示货币值,尤其是在货币值非常大,并且需要绝对精度的时候。BigInt
可以表示任意大小的整数,不会出现精度丢失的问题。
总而言之,选择 Decimal
还是 BigInt
取决于你的具体需求。如果你需要精确表示十进制数值,并且数值范围在 Decimal
类型的可表示范围内,那么 Decimal
是一个不错的选择。如果你需要表示任意大小的整数,并且需要绝对精度,那么 BigInt
更为合适。
常见问题解答
1. 为什么 Prisma 会将 Decimal 类型的值返回为字符串?
这是因为 Prisma 底层使用了 decimal.js 库来处理 Decimal 类型,而 decimal.js 默认会将数值转换为字符串表示,以避免 JavaScript 中浮点数精度丢失的问题。
2. 如何让 Prisma 返回数值而不是字符串?
有两种方法:
- 在查询结果上进行转换,例如使用
parseFloat()
或Number()
函数将字符串转换为数值。 - 利用 Prisma 的类型转换功能,在 Prisma schema 中定义自定义类型,并将 Decimal 字段的类型指定为
number
。
3. 使用 Decimal 类型表示货币值是否合适?
是的,Decimal 类型能够精确地表示十进制数值,避免了浮点数精度丢失带来的问题,这在处理货币计算时尤为重要。
4. BigInt 类型是否也可以用来表示货币值?
可以,BigInt 可以表示任意大小的整数,不会出现精度丢失的问题,尤其适合表示非常大的货币值,并且需要绝对精度的情况。
5. 如何选择 Decimal 和 BigInt 类型来表示货币值?
如果需要精确表示十进制数值,并且数值范围在 Decimal 类型的可表示范围内,那么 Decimal 是一个不错的选择。如果需要表示任意大小的整数,并且需要绝对精度,那么 BigInt 更为合适。