Access other fields in getter - node.js

I'm trying to make it that every time I get subtotal, it adds 2 other fields, productTotal, and tax.
Here's my code:
const cost = new mongoose.Schema({
payment: {
productTotal: Number,
tax: Number,
subtotal: Number, // (productTotal + tax)
}
});
const Cost = mongoose.model('Cost', cost);
How can I add 2 feilds from the same schema when getting a different field?

You can achieve that in mongoose by creating a virtual field for subtotal. The mongoose reference documents this pretty well here: https://mongoosejs.com/docs/tutorials/virtuals.html.
EDIT:
The code snippet below shows how you can define a cost schema that has a subtotal virtual on the payment subdocument:
const PaymentSchema = new Schema({
productTotal: { type: Number, default: 0 },
tax: { type: Number, default: 0 },
});
PaymentSchema.virtual('subtotal').get(function () { return this.productTotal + this.tax; });
const CostSchema = new Schema({
payment: PaymentSchema,
});
From the above snippet you can get the subtotal from a Cost document instance via cost.payment.subtotal.

Related

Mongoose delete records after certain time

I have a mongoose Schema which looks like this:
const USERS_DATA = new Schema({
_id: Number,
name: String,
img: String,
date: Date,
phone: String,
article: String,
createdAt: {
type: Date,
required: true,
default: Date.now,
index: { expires: '3d' }
}
},
{
collection: "users",
_id: false,
}
);
I need to push data to this schema.
const User = mongoose.model("users", USERS_DATA);
function pushToDB() {
const newUser = new User({
name: INPUT.name,
img: INPUT.img,
date: INPUT.date,
phone: INPUT.phone,
article: INPUT.article,
});
newUser.save(function (err) {
mongoose.disconnect();
if (err) return console.log(err);
});
}
This data have to be deleted after 3 days when it was pushed to database. How to implement it in node.js? I found it really confusing and tried lots of code. Any answers are appreciated! Thanks
P.S. I use mongoDb Atlas
You should separate the process to push the data into the database from the process to delete it after 3 days. You have already the first part :).
For the second part, you can write a function deleteOldDocument. This function will query for documents in DB that are created for 3 days or more, and delete them. Then, you can run this function periodically, 1 time per day for example.
The pseudo-code, in case you need it :
async function deleteOldDocument() {
const 3DaysAgo = ...; // here you can subtract 3 days from now to obtain the value
// search for documents that are created from 3 days or more, using $lt operator
const documentToDelete = await User.find({"created_at" : {$lt : 3DaysAgo }});
// delete documents from database
.....
// recall the function after 1 days, you can change the frequence
setTimeOut(async function() {
await deleteOldDocument();
}), 86400);
}
// call deleteOldDocument to start the loop
deleteOldDocument();

How to make Mongoose Schema id generate a 16 digits random number

I'm new to mongoose. I'm creating a model (creditnote) that consists of a 16 digits unique reference (serves as primary key) and an integer that represents the number of credits.
I want the reference to be the model's id and to be an auto-generated 16 digits number. How can I achieve this?
Right now I have the following code:
var mongoose = require('mongoose');
// Setup schema
var creditnoteSchema = mongoose.Schema({
reference: {
type: mongoose.ObjectId,
required: true,
default: function(){
// Generate 16 digits random number
number = (Math.random()+' ').substring(2,10)+(Math.random()+' ').substring(2,10);
}
},
amount: {
type: Number,
required: true,
validate: {
validator: Number.isInteger,
message: '{VALUE} is not an integer value'
}
}
});
All objects created in MongoDB have a property _id which serves as a unique ID. You can also use ObjectId to generate a unique key, like this:
const {ObjectId} = require('mongodb');
console.log(ObjectId());

Create custom getter

How can I make a field in a document have a custom getter? I want the subtotal field to return productTotal + tax anytime I get subtotal.
const item = new mongoose.Schema({
payment: {
productTotal: Number,
tax: Number,
subtotal: Number, // (productTotal + tax)
}
});
const Item = mongoose.model('Item', item);
I can't use virtualization since I want to also be able to use find on subtotal.
Hi I've never used mongoose but we can practicly create a prototype for Item model I'm guessing maybe this code would work?
const item = new mongoose.Schema({
payment: {
productTotal: Number,
tax: Number,
},
});
const Item = mongoose.model("Item", item);
Item.prototype.subtotal = function () {
return this.payment.productTotal + this.payment.tax;
};
const newItem = new Item({ payment: { productTotal: 10, tax: 10 } });
// Obv you need to call it as function :)
console.log(newItem.subtotal());
I've checked the docs from mongoose couldn't find anything related with getter

mongoose autoincrement counter per unique value

I have the two models, entity and post, and I'm trying to create an auto incremented counter on post for each unique entity:
//entity
var entitySchema = mongoose.Schema({
name: String,
counter: Number,
});
//post
var postSchema = mongoose.Schema({
test: String,
entity: {
type: Schema.Types.ObjectId,
ref: 'entity'
},
ticketNumber: Number //this needs to auto increment starting at zero PER user, so entity A has a 1+, entity 2 has a 1+, etc
});
I can have a sequence on entity, check it every time I create a post and use it, but that could possibly have duplicates.
I found a post suggesting an even on pre post'save', but that wouldn't be unique to each entity, just unique overall.
Any way to get this working on the model itself / a better way of doing this?
You can use the npm package called mongoose-auto-increment.
Your connection would look like this:
var autoIncrement = require('mongoose-auto-increment');
var connection = mongoose.connect('YOUR CONNECTION');
autoIncrement.initialize(connection);
your Schema would look like this:
var postSchema = mongoose.Schema({
test: String,
entity: {
type: Schema.Types.ObjectId,
ref: 'entity'
},
ticketNumber: Number
});
postSchema.plugin(autoIncrement.plugin, { model: 'NAME YOUR MODEL', field: 'ticketNumber', startAt: 0, incrementBy: 1 });

Mongodb store sales data by month schema

How should I defined my schema if I want to retrieve/insert monthly sales figure? like this?
sales: [{
Jan:Number,
Feb:Number
}]
You may simply create a schema as following
var monthlySale = new Schema({
sale: Number,
month: Number, //may be string
year: Number
});
var MonthlySale = mongoose.model('MonthlySale', monthlySale);
and you can insert
var sale = new MonthlySale({ sale: 5000, month: 7, year: 2016})
sale.save(function(err, saleObj) {
if(err)
console.log('Unable to create sale')
else
console.log('New sale created')
});
and you may find as following
MonthlySale.findOne({month: 7, year: 2016}, function(err, sale) {
if(err)
console.log('Unable to fetch sale')
else
console.log('Sale : ', sale)
});
You should not use values as field name in mongodb schema, that makes it hard to query on it. It is upto you what data you want to save, you can save date of each month of the year, or save month and year field separately.
Below are two schema I think you can use.
sales:[
{
month_date: {type: Date},
amount: {type: Number}
}
]
sales:[
{
month: {type: String},
year: {type: Number},
amount: {type: Number}
}
]
With these schema you can easily query on these records
You can use joi validation, here is an example... (Note: i'm making it dynamic by exporting it so that you can use anywhere you want to...)
So, you have to import joi module first. See below...
var joi = require('joi');
Now below is the validators of string, number etc...
var string = joi.string().min(2).max(50); //you can also set max,min..
var bool = joi.boolean();
var number = joi.number().min(1).max(999999999).required();
var object = function object(obj) {
return joi.object().keys(obj);
}
var array = function array(ary) {
return joi.array().items(ary).min(1);
}
Now just export these all...
module.exports = {
string: string,
bool: bool,
number: number,
object: object,
array: array
}
And now you can import the file in which you kept it and can use these validators.
var schema = {
firstname: string.label('user firstname'),
lastname: string.label('user lastname'),
gender: bool.label('user gender'),
age: number.label('user age')
};

Resources