Correct way to do Ledger system in MongoDB - mongodb

So we are trying to work out in what format do we store money values in MongoDB we are talking dealing with cents.
For example if someone gets charged 0.04 but we take 30% commission we should get 0.012
But I am sure that we should not be storing data like $0.012 or even in 0.012
because technically you could end up with 0.0125 for example.
I read that you should use something like this. trans_amount | decimal | 10 | Deposit amount
Meaning in MongoDB it would be stored like:
{
trans_amount: NumberInit(00125)
}
However the issue is that if $10 was spend it would be store like
{
trans_amount: NumberInit(01000)
}
Now if we go back to the first above example and try to code it out we would get $1.25 instead of the $0.0125 it should be.
Now I am guessing the correct way would be to have 12 digits?
000000000000
However this works up to when you have a customer that wants to spend Trillion dollars at once (not that that would happen - but you never know)
So before I go and code a transaction database I want to work out the correct way to store cents and dollars in MongoDB for accounting.
According to Mongodb they recommend the following:
{
price: { display: "9.99", approx: 9.9900000000000002, currency: "USD" },
fee: { display: "0.25", approx: 0.2499999999999999, currency: "USD" }
}
OR
{ price: 9990, currency: "USD" }
However does approx automatically get done by MongoDB - My guess is no and I would have to work that out myself.

There are couple of ways to do this:
{ price: 9990, currency: "USD" } //See it is not string
As in the above example, you can store. Here the thing is that number of decimals is fixed at any point of time.
The scale factor is consistent for a currency; i.e. same scaling factor for a given currency. The scale factor is a constant and known property of the currency; i.e applications can determine the scale factor from the currency.
In another way, you can use other type:
{
price: { display: "9.99", approx: 9.9900000000000002, currency: "USD" },
fee: { display: "0.25", approx: 0.2499999999999999, currency: "USD" }
}
Here, approx describes exact decimal value with more decimal. The value you query is represented by display field.
In one field, encode the exact monetary value as a non-numeric data type; e.g., BinData or a string. In the second field, store a double-precision floating point approximation of the exact value.

Related

How to markup an electricity rate in Schema.org?

What are the correct entities and how to nest them to declare an electricity rate for an electricity provider?
Example:
Provider: John Doe Provider
Rate: John Doe’s Special Electricity Rate
Basefee: 9,90 EUR
Working Price: 0,27 EUR / kWh
Rating: 5 from 5 Stars
I agree with the recommendation of Andrew Morton, however, I would like to clarify some details. To identify kilowatt-hours, I recommend that you use an international identifier from UNECE. E.g.:
"priceSpecification":{
"#type":"UnitPriceSpecification",
"price":"0.27",
"priceCurrency":"EUR",
"referenceQuantity": {
"#type":"QuantitativeValue",
"value":"1",
"unitCode":"KWH",
"sameAs":"http://www.unece.org/fileadmin/DAM/cefact/recommendations/bkup_htm/add3hk.htm"
}
}
In the content of a web page, it may be useful to use the HTML element abbr for an abbreviation of kilowatt-hours
Use the following recommendation for the price property:
Use '.' (Unicode 'FULL STOP' (U+002E)) rather than ',' to indicate a
decimal point. Avoid using these symbols as a readability separator.
Update 2019-09-30 related to the following question of JKB:
... But how to extend this example to also declare „base fee“? And, in
addition, set the name of the supplier?
The following markup may probably help you:
{"#context": "http://schema.org/",
"#type":"Service",
"serviceType":"Supply of electricity",
"provider":{
"#type":"LocalBusiness",
"name":"John Doe Provider"
},
"offers":{
"#type":"Offer",
"name":"Base fee",
"price": "9.90",
"priceCurrency": "EUR",
"priceSpecification":{
"#type":"UnitPriceSpecification",
"name":"Working Price",
"price":"0.27",
"priceCurrency":"EUR",
"referenceQuantity": {
"#type":"QuantitativeValue",
"value":"1",
"unitCode":"KWH",
"sameAs":"http://www.unece.org/fileadmin/DAM/cefact/recommendations/bkup_htm/add3hk.htm"
}
}
}
}
I set here the top-level type such as Service however, I do not have a clear understanding of whether this is a service or a product. Therefore you need to clearly determine whether the supply of electricity is a service or is it an intangible product. If this is a product, then adjust this markup for the type Product.

Best way to store and organize data in MongoDB

I have a users in MongoDB and each user has an interface allowing them to set their current state of hunger being a combination of "hungry", "not hungry", "famished", "starving", or "full"
Each user can enter a multiple options for any period of time. For example, one use case would be "in the morning, record how my hunger is" and the user can put "not hungry" and "full". They can record how their hunger is at any time in the day, and as many times as they want.
Should I store the data as single entries, and then group the data by a date in MongoDB later on when I need to show it in a UI? Or should I store the data as an array of the options the user selected along with a date?
It depends on your future queries, and you may want to do both. Disk space is cheaper than processing, and it's always best to double your disk space than double your queries.
If you're only going to map by date then you'll want to group all users/states by date. If you're only going to map by user then you'll want to group all dates/states by user. If you're going to query by both, you should just make two Collections to minimize processing. Definitely use an array for the hunger state in either case.
Example structure for date grouping:
{ date: '1494288000',
time-of-day: [
{ am: [
{ user: asdfas, hunger-state: [hungry, full] },
{ user: juhags, hunger-state: [full] }
],
pm: [
{ user: asdfas, hunger-state: [hungry, full] },
{ user: juhags, hunger-state: [full] }
]}]}
It depends on how you are going to access it. If you want to report on a user's last known state, then the array might be better:
{
user_id: '5358e4249611f4a65e3068ab',
timestamp: '2017-05-08T17:30:00.000Z',
hunger: ['HUNGRY','FAMISHED'],
}
The timestamps of multiple records might not align perfectly if you are passing in the output from new Date() (note the second record is 99 ms later):
{
user_id: '5358e4249611f4a65e3068ab',
timestamp: '2017-05-08T17:30:00.000Z',
hunger: 'HUNGRY',
}
{
user_id: '5358e4249611f4a65e3068ab',
timestamp: '2017-05-08T17:30:00.099Z',
hunger: ['FAMISHED',
}
You should probably look at your data model though and try to get a more deterministic state model. Maybe:
{
user_id: '5358e4249611f4a65e3068ab',
timestamp: '2017-05-08T17:30:00.000Z',
isHungry: true,
hunger: 'FAMISHED',
}

Storing functions in MongoDB in different collections?

Say that I have a business that represents users who spend a certain amount of time to produce certain quantities of stuff. I want each user to be free to create their own algorithm, or formula, for determining the price that they charge for their work:
Users Collection, with possibly thousands of different users.
{
userId: 'sdf23d23dwew',
price: function(time, qty){
// some algorithm
}
},
{
userId: '23f5gf34f',
price: function(time, qty){
// another algorithm
}
},
{
userId: '7u76565',
price: function(time, qty){
// yet another algorithm
}
},
{
userId: 'w45y65yh4',
price: function(time, qty){
// something else
}
}
//and on and on and on...
Now, JSON doesn't support functions and neither does MongoDB. BUT this use-case of possibly thousands of users, each with the freedom to create their own unique method of determining their own prices, seems to me like being able to store functions inside of their user document would be ideal.
I certainly don't feel like it's a good idea to just store all these thousands of functions in a JS file on the server that somehow gets referenced by a userId when it's needed...
Is there a solution for this case?

MongoDB Mongoose dynamic fields

I'm developing a website in which each user has a number of balances for different currencies. Throughout the lifetime of the website I will regularly add new currencies.
I'm trying to figure out the best way to store the balances using mongoose. I currently atore the balances like this:
var UserSchema = new Schema({
...
balances: {
mck: {
type: Number,
default: 100.0,
addresses: String
},
btc:{
type: Number,
default: 10.0,
address: String
}
}
});
But it doesn't seem like the best approach. each time I want to add a new currency the existing documents will not contain it. Are there disadvantages to allowing documents in the database which are out of sync with the schema?
I thought of making the schema more dynamic by using a subdocument to store currencies and their respective balances like this:
var BalanceSchema = new Schema({
currency: String,
amount: Number,
address: String
});
But there would be a painful number of callbacks to deal with when changing balances etc.
Which of these methods would be the best approach? Or is there another I have missed?
If you have the need to add currencies dynamically in the future, you should opt to have "balances" as an array.
balances: [
{
curr: "mck",
bal: 123,45
},
{
curr: "btc",
bal: 42
}
]
It helps with queries in the future (like so) and it also gives you a lot of flexibility with each document.
Or why not go for a flat schema like:
{
user: "user1",
currency1balance:54,76,
currency5balance:1024
}

How would you model this in MongoDB?

There are products with a name and price.
Users log about products they have bought.
# option 1: embed logs
product = { id, name, price }
user = { id,
name,
logs : [{ product_id_1, quantity, datetime, comment },
{ product_id_2, quantity, datetime, comment },
... ,
{ product_id_n, quantity, datetime, comment }]
}
I like this. But if product ids are 12 bytes long, quantity and datetime are 32-bit (4 bytes) integers and comments 100 bytes on average, then the size of one log is 12+4+4+100 = 120 bytes. The maximum size of a document is 4MB, so maximum amount of logs per user is 4MB/120bytes = 33,333. If assumed that a user logs 10 purchases per day, then the 4MB limit is reached in 33,333/10 = 3,333 days ~ 9 years. Well, 9 years is probably fine, but what if we needed to store even more data? What if the user logs 100 purchases per day?
What is the other option here? Do I have to normalize this fully?
# option 2: normalized
product = { id, name, price }
log = { id, user_id, product_id, quantity, datetime, comment }
user = { id, name }
Meh. We are back to relational.
if the size is the main concern, you can go ahead with option 2 with mongo DbRef.
logs : [{ product_id_1, quantity, datetime, comment },
{ product_id_2, quantity, datetime, comment },
... ,
{ product_id_n, quantity, datetime, comment }]
and embed this logs inside user using Dbref, something like
var log = {product_id: "xxx", quantity:"2", comment:"something"}
db.logs.save(log)
var user= { id:"xx" name : 'Joe', logs : [ new DBRef('logs ', log._id) ] }
db.users.save(user)
Yes, option 2 is your best bet. Yes, you're back to a relational model, but then, your data is best modeled that way. I don't see a particular downside to option 2, its your data that is requiring you to go that way, not a bad design process.