Пока я создавал свое серверное приложение NestJs, я хотел хранить некоторые финансовые данные. Первый вопрос, с которым я столкнулся, заключался в том, какой тип схемы должен быть для хранения таких данных, где я хочу поддерживать точность данных.

Decimal128 оказался назначенным официальным кандидатом для хранения финансовых данных.

Вот моя первоначальная реализация схемы:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import mongoose, { Decimal128, HydratedDocument, Types } from 'mongoose';

export type UserDocument = HydratedDocument<User>;

@Schema({
  toJSON: {
    getters: true,
  },
})
export class User {
  @Prop()
  firstName: string;

  @Prop()
  lastName: string;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
  })
  total_invested: Decimal128;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
  })
  target_returns: Decimal128;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
  })
  target_profit_percent: Decimal128;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
  })
  actual_returns: Decimal128;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
  })
  actual_profit_percent: Decimal128;
}

export const UserSchema = SchemaFactory.createForClass(User);

Была одна небольшая проблема, с которой я вскоре столкнулся. База данных вернет данные столбца Decimal128 в следующем формате:

{
    "_id": "64d50a0bf9e3e104920dec6a",
    "firstName": "shiva",
    "lastName": "chaturvedi",
    "total_invested": {
        "$numberDecimal": "0"
    },
    "target_returns": {
        "$numberDecimal": "0"
    },
    "target_profit_percent": {
        "$numberDecimal": "0"
    },
    "actual_returns": {
        "$numberDecimal": "0"
    },
    "actual_profit_percent": {
        "$numberDecimal": "0"
    },
    "__v": 0,
    "id": "64d50a0bf9e3e104920dec6a"
}

… тогда как я хотел, чтобы база данных возвращала преобразованные результаты или, проще говоря, данные в старом добром формате пары ключ-значение.

Решение: используйте геттеры

Реализовать getters в свойствах вашей схемы очень просто.

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import mongoose, { Decimal128, HydratedDocument, Types } from 'mongoose';

export type UserDocument = HydratedDocument<User>;

@Schema()
export class User {
  @Prop()
  firstName: string;

  @Prop()
  lastName: string;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
    get: (v: Types.Decimal128) => v.toString(),
  })
  total_invested: Decimal128;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
    get: (v: Types.Decimal128) => v.toString(),
  })
  target_returns: Decimal128;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
    get: (v: Types.Decimal128) => v.toString(),
  })
  target_profit_percent: Decimal128;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
    get: (v: Types.Decimal128) => v.toString(),
  })
  actual_returns: Decimal128;

  @Prop({
    default: new Types.Decimal128('0'),
    type: Types.Decimal128,
    get: (v: Types.Decimal128) => v.toString(),
  })
  actual_profit_percent: Decimal128;
}

export const UserSchema = SchemaFactory.createForClass(User);

Теперь давайте снова протестируем API.

«Что я упускаю?» — подумал я.

После небольшой прогулки по Интернету добрый самаритянин указал, что нам также нужно установить флаг getters как true в декораторе @Schema, как показано ниже:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import mongoose, { Decimal128, HydratedDocument, Types } from 'mongoose';

export type UserDocument = HydratedDocument<User>;

@Schema({
  toJSON: {
    getters: true,
  },
})

Это в основном позволяет свойствам выполнять/использовать свои собственные функции получения.

Тестируем снова!

Аллилуйя 🎉 🎉

Хотите узнать больше о типе Decimal128? Прочтите эту прекрасную статью, написанную Ken W. Alger на официальном сайте MongoDB.

Благодарственное письмо ❤️

Спасибо, что заглянули. Надеюсь, вы найдете этот блог полезным. Если да, то, пожалуйста, подпишитесь на меня и помогите мне набрать 1 000 подписчиков 🙏🏻. Это действительно побудит меня выпускать больше контента.

P.S.: Если вы чувствуете, что что-то можно улучшить или вам не хватает надлежащего объяснения, напишите мне в поле для комментариев или напишите мне на [email protected]. В конце концов, ты тоже можешь научить меня кое-чему.

Спасибо, что дочитали до конца. Пожалуйста, следите за автором и этой публикацией. Посетите Stackademic, чтобы узнать больше о том, как мы демократизируем бесплатное обучение программированию по всему миру.