Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node JS Visitors Mongoose Schema, count visits by years, months, weeks, days

Hi this is a Schema to count the amount of visitors to my sites, i have multiple domains.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const VisitorSchema = Schema({
    domain: String,
    count: Number
});

module.exports = mongoose.model('Visitor', VisitorSchema);

I would like to save in mongoDB the amount of visitors to my sites in periods of time. At this point i can increase the 'count' property but what if i want to organize by years, months and weeks.

async function saveVisitor(domain){
    let visitors = await Visitor.findOne({domain});
    if(visitors == null) {
        const startCount = new Visitor({
            domain: domain,
            count: 1
        });
        startCount.save();
    } else {
        visitors.count++;
        visitors.save();
    }
}

So my question is: how can i create the years as dynamic properties in mongoose?. What i have in mind is to start counting from a firstVisitDate property. Thanks in advance.

{ 
    domain: String,
    firstVisitDate: Date,
    2022: {
        today: Number,
        week: Number,
        month: Number,
        year: Number
    },
    2023: {
        today: Number,
        week: Number,
        month: Number,
        year: Number,
    }
    total: Number
}
like image 651
sonEtLumiere Avatar asked Feb 03 '26 11:02

sonEtLumiere


1 Answers

You can use node-cron to automatize jobs and reset visitors counter every midnight: https://www.npmjs.com/package/node-cron

const nodeCron = require('node-cron');

const cron = {
    run: function() {
        nodeCron.schedule('* * * * *', () => {
            updateVisitorDateCounter();
        })
    } 
};
cron.run(); // run every midnight

updateVisitorDateCounter function:

async function updateVisitorDateCounter() {
    const date = new Date();

    if(date.getHours() + date.getMinutes() != 0) return;// prevent restart 'today' counter if server restarts (only works with same time setted in cron)
    const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
    const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    const dayName = days[date.getDay()];
    const monthName = months[date.getMonth()];
    
    const domainVisitors = await Visitor.find();

    for(let visitor of domainVisitors) {
        visitor.today = 0;
        const visitorUpdated = await visitor.save();
    }
    
    const newWeek = dayName === 'Sunday' ? true : false;
    if(newWeek) {
        for(let visitor of domainVisitors) {
            visitor.week = 0;
            const visitorUpdated = await visitor.save();
        }
    }

    const newMonth = date.getDate() === 1 ? true : false;   //first day of month
    if(newMonth) {
        for(let visitor of domainVisitors) {    
            if(visitor.history.length == 0) {
                visitor.history = [{ year: date.getFullYear(), months: [{name: monthName, counter: visitor.month}] }]
            } else {
                let historyMonths = visitor.history.find(x => x.year === date.getFullYear()).months;
                historyMonths.push({name: monthName, counter: visitor.month});
                visitor.history = [{ year: date.getFullYear(), months: historyMonths }];
            }
            visitor.month = 0;
            const visitorUpdated = await visitor.save();
        }
    }

    const newYear = date.getMonth() === 0 && date.getDate() === 1 ? true : false;
    if(newYear) {
        // code here ...
    }
}
like image 170
Leandro Perez Avatar answered Feb 06 '26 00:02

Leandro Perez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!