{"id":57961,"date":"2023-08-19T16:26:59","date_gmt":"2023-08-19T10:56:59","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=57961"},"modified":"2024-01-02T17:37:26","modified_gmt":"2024-01-02T12:07:26","slug":"simple-way-to-handle-monetary-data-in-mongodb-in-a-nestjs-application","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/simple-way-to-handle-monetary-data-in-mongodb-in-a-nestjs-application\/","title":{"rendered":"Simple way to handle monetary data in MongoDB in a NestJs application"},"content":{"rendered":"<section class=\"section section--body\">\n<div class=\"section-divider\"><\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<figure class=\"graf graf--figure\"><img decoding=\"async\" class=\"graf-image\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/1rFD5STIrpaTvM4f9KJ_-cg.png\" data-image-id=\"1*rFD5STIrpaTvM4f9KJ_-cg.png\" data-width=\"1400\" data-height=\"817\" data-is-featured=\"true\" \/><\/figure>\n<p>While building my backend NestJs application, I wanted to store some financial data. The first question I ran into was what schema Type should be for storing data where I want to maintain the data precision.<\/p>\n<p>Decimal128 came out to be the prescribed official candidate to store the financial data.<\/p>\n<p>Here\u2019s my initial schema implementation:<\/p>\n<pre class=\"graf graf--pre graf--preV2\" data-code-block-mode=\"1\" data-code-block-lang=\"python\"><span class=\"pre--content\"><span class=\"hljs-keyword\">import<\/span> { Prop, Schema, SchemaFactory } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@nestjs\/mongoose'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> mongoose, { Decimal128, HydratedDocument, Types } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'mongoose'<\/span>;\r\n\r\nexport <span class=\"hljs-built_in\">type<\/span> UserDocument = HydratedDocument&lt;User&gt;;\r\n\r\n<span class=\"hljs-meta\">@Schema(<span class=\"hljs-params\">{\r\n  toJSON: {\r\n    getters: true,\r\n  },\r\n}<\/span>)<\/span>\r\nexport <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title class_\">User<\/span> {\r\n<span class=\"hljs-meta\">  @Prop()<\/span>\r\n  firstName: string;\r\n\r\n<span class=\"hljs-meta\">  @Prop()<\/span>\r\n  lastName: string;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n  }<\/span>)<\/span>\r\n  total_invested: Decimal128;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n  }<\/span>)<\/span>\r\n  target_returns: Decimal128;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n  }<\/span>)<\/span>\r\n  target_profit_percent: Decimal128;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n  }<\/span>)<\/span>\r\n  actual_returns: Decimal128;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n  }<\/span>)<\/span>\r\n  actual_profit_percent: Decimal128;\r\n}\r\n\r\nexport const UserSchema = SchemaFactory.createForClass(User);<\/span><\/pre>\n<p class=\"graf graf--p\">There was one small issue that I soon ran into. The database would return the Decimal128 column data in this format:<\/p>\n<pre class=\"graf graf--pre graf--preV2\" data-code-block-mode=\"1\" data-code-block-lang=\"bash\"><span class=\"pre--content\">{\r\n    <span class=\"hljs-string\">\"_id\"<\/span>: <span class=\"hljs-string\">\"64d50a0bf9e3e104920dec6a\"<\/span>,\r\n    <span class=\"hljs-string\">\"firstName\"<\/span>: <span class=\"hljs-string\">\"shiva\"<\/span>,\r\n    <span class=\"hljs-string\">\"lastName\"<\/span>: <span class=\"hljs-string\">\"chaturvedi\"<\/span>,\r\n    <span class=\"hljs-string\">\"total_invested\"<\/span>: {\r\n        <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$numberDecimal<\/span>\"<\/span>: <span class=\"hljs-string\">\"0\"<\/span>\r\n    },\r\n    <span class=\"hljs-string\">\"target_returns\"<\/span>: {\r\n        <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$numberDecimal<\/span>\"<\/span>: <span class=\"hljs-string\">\"0\"<\/span>\r\n    },\r\n    <span class=\"hljs-string\">\"target_profit_percent\"<\/span>: {\r\n        <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$numberDecimal<\/span>\"<\/span>: <span class=\"hljs-string\">\"0\"<\/span>\r\n    },\r\n    <span class=\"hljs-string\">\"actual_returns\"<\/span>: {\r\n        <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$numberDecimal<\/span>\"<\/span>: <span class=\"hljs-string\">\"0\"<\/span>\r\n    },\r\n    <span class=\"hljs-string\">\"actual_profit_percent\"<\/span>: {\r\n        <span class=\"hljs-string\">\"<span class=\"hljs-variable\">$numberDecimal<\/span>\"<\/span>: <span class=\"hljs-string\">\"0\"<\/span>\r\n    },\r\n    <span class=\"hljs-string\">\"__v\"<\/span>: 0,\r\n    <span class=\"hljs-string\">\"id\"<\/span>: <span class=\"hljs-string\">\"64d50a0bf9e3e104920dec6a\"<\/span>\r\n}<\/span><\/pre>\n<p class=\"graf graf--p\">Whereas I wanted the database to return transformed results or, simply put, data in a good old-fashioned key-value pair format.<\/p>\n<h3 class=\"graf graf--h3\">Solution: Use\u00a0Getters<\/h3>\n<p class=\"graf graf--p\">Implementing <code class=\"markup--code markup--p-code\">getters<\/code> your schema props is very easy.<\/p>\n<pre class=\"graf graf--pre graf--preV2\" data-code-block-mode=\"1\" data-code-block-lang=\"python\"><span class=\"pre--content\"><span class=\"hljs-keyword\">import<\/span> { Prop, Schema, SchemaFactory } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@nestjs\/mongoose'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> mongoose, { Decimal128, HydratedDocument, Types } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'mongoose'<\/span>;\r\n\r\nexport <span class=\"hljs-built_in\">type<\/span> UserDocument = HydratedDocument&lt;User&gt;;\r\n\r\n<span class=\"hljs-meta\">@Schema()<\/span>\r\nexport <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title class_\">User<\/span> {\r\n<span class=\"hljs-meta\">  @Prop()<\/span>\r\n  firstName: string;\r\n\r\n<span class=\"hljs-meta\">  @Prop()<\/span>\r\n  lastName: string;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n    get: (v: Types.Decimal128) =&gt; v.toString(),\r\n  }<\/span>)<\/span>\r\n  total_invested: Decimal128;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n    get: (v: Types.Decimal128) =&gt; v.toString(),\r\n  }<\/span>)<\/span>\r\n  target_returns: Decimal128;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n    get: (v: Types.Decimal128) =&gt; v.toString(),\r\n  }<\/span>)<\/span>\r\n  target_profit_percent: Decimal128;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n    get: (v: Types.Decimal128) =&gt; v.toString(),\r\n  }<\/span>)<\/span>\r\n  actual_returns: Decimal128;\r\n\r\n<span class=\"hljs-meta\">  @Prop(<span class=\"hljs-params\">{\r\n    default: new Types.Decimal128(<span class=\"hljs-string\">'0'<\/span>),\r\n    <span class=\"hljs-built_in\">type<\/span>: Types.Decimal128,\r\n    get: (v: Types.Decimal128) =&gt; v.toString(),\r\n  }<\/span>)<\/span>\r\n  actual_profit_percent: Decimal128;\r\n}\r\n\r\nexport const UserSchema = SchemaFactory.createForClass(User);<\/span><\/pre>\n<p class=\"graf graf--p\">Now, let\u2019s test the API again.<\/p>\n<figure class=\"graf graf--figure\"><img decoding=\"async\" class=\"graf-image\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/1r2REH_0Imhn0fN7TJMGJIQ.png\" data-image-id=\"1*r2REH_0Imhn0fN7TJMGJIQ.png\" data-width=\"1250\" data-height=\"1456\" \/><\/figure>\n<figure class=\"graf graf--figure\"><img decoding=\"async\" class=\"graf-image\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/1Wj8_uPNK9x5zgUnBhMq8Bw.gif\" data-image-id=\"1*Wj8_uPNK9x5zgUnBhMq8Bw.gif\" data-width=\"498\" data-height=\"278\" \/><\/figure>\n<p class=\"graf graf--p graf--startsWithDoubleQuote\">\u201cWhat am I missing?\u201d I wondered.<\/p>\n<p class=\"graf graf--p\">After a short walk on the internet, a good samaritan pointed out that we also need to set <code class=\"markup--code markup--p-code\">getters<\/code> flag as <code class=\"markup--code markup--p-code\">true<\/code> on the <code class=\"markup--code markup--p-code\">@Schema<\/code> decorator as illustrated below:<\/p>\n<pre class=\"graf graf--pre graf--preV2\" data-code-block-mode=\"1\" data-code-block-lang=\"typescript\"><span class=\"pre--content\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">Prop<\/span>, <span class=\"hljs-title class_\">Schema<\/span>, <span class=\"hljs-title class_\">SchemaFactory<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@nestjs\/mongoose'<\/span>;\r\n<span class=\"hljs-keyword\">import<\/span> mongoose, { <span class=\"hljs-title class_\">Decimal128<\/span>, <span class=\"hljs-title class_\">HydratedDocument<\/span>, <span class=\"hljs-title class_\">Types<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'mongoose'<\/span>;\r\n\r\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">type<\/span> <span class=\"hljs-title class_\">UserDocument<\/span> = <span class=\"hljs-title class_\">HydratedDocument<\/span>&lt;<span class=\"hljs-title class_\">User<\/span>&gt;;\r\n\r\n<span class=\"hljs-meta\">@Schema<\/span>({\r\n  <span class=\"hljs-attr\">toJSON<\/span>: {\r\n    <span class=\"hljs-attr\">getters<\/span>: <span class=\"hljs-literal\">true<\/span>,\r\n  },\r\n})<\/span><\/pre>\n<p class=\"graf graf--p\">This enables the props to execute\/use their getter functions.<\/p>\n<p class=\"graf graf--p\">Let\u2019s test again!<\/p>\n<figure class=\"graf graf--figure\"><img decoding=\"async\" class=\"graf-image\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/1OfP39j3hZ0l4AfNRybVJnQ.png\" data-image-id=\"1*OfP39j3hZ0l4AfNRybVJnQ.png\" data-width=\"1088\" data-height=\"1104\" \/><\/figure>\n<p class=\"graf graf--p\">Hallelujah ? ?<\/p>\n<blockquote class=\"graf graf--blockquote\"><p>Want to know more about Decimal128 Type? Read <a class=\"markup--anchor markup--blockquote-anchor\" href=\"https:\/\/www.mongodb.com\/developer\/products\/mongodb\/bson-data-types-decimal128\/\" target=\"_blank\" rel=\"noopener noreferrer\" data-href=\"https:\/\/www.mongodb.com\/developer\/products\/mongodb\/bson-data-types-decimal128\/\">this<\/a> beautiful article written by <a class=\"markup--anchor markup--blockquote-anchor\" href=\"https:\/\/www.mongodb.com\/developer\/author\/ken-w-alger\/\" target=\"_blank\" rel=\"noopener noreferrer\" data-href=\"https:\/\/www.mongodb.com\/developer\/author\/ken-w-alger\/\">Ken W. Alger<\/a> on MongoDB official website.<\/p><\/blockquote>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"section section--body\">\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<p class=\"graf graf--p\">P.S.: If you feel something can be improved or lacks proper explanation, drop us a note in the comment section below, and we&#8217;ll try to<\/p>\n<\/div>\n<\/div>\n<\/section>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>While building my backend NestJs application, I wanted to store some financial data. The first question I ran into was what schema Type should be for storing data where I want to maintain the data precision. Decimal128 came out to be the prescribed official candidate to store the financial data. Here\u2019s my initial schema implementation: [&hellip;]<\/p>\n","protected":false},"author":1535,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":53},"categories":[4684,1185,1],"tags":[4846,5327],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57961"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1535"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=57961"}],"version-history":[{"count":4,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57961\/revisions"}],"predecessor-version":[{"id":59679,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/57961\/revisions\/59679"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=57961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=57961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=57961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}