can anyone help me how can i save documents in mongodb using nodejs driver with
a field createdDate in the date format dd.mm.yyyy
I have tried to do so but in schema on type:date is getting accepted
and when type:string i am still unable to save the date
let today = new Date();
let day = today.getDate();
let month = today.getMonth() + 1;
let year = today.getFullYear();
let hour = today.getHours();
let minutes = today.getMinutes();
let seconds = today.getSeconds();
crdate =`${day}.${month}.${year}.${hour}.${minutes}.${seconds}`
const order = new VendorOrder({
...req.body,
vendorOrders: req._id,
crdate
});
try {
await order.save();
res.status(201).send(order);
} catch (e) {
res.status(400).json({
message: "unable to create order"
});
}
};
Related
I have a Scheduler where I can post scheduled tweets and threads and it will post through my twitter account the whole backend is based on Node JS.
So right now for Posting scheduled Tweets and Tweet threads with images I'm using mongoDB, storing the base64 string data, but I don't want to store such a big data to mongo, is it possible to upload images to AWS S3 first and then when time matches as Scheduled time that Image will be fetched again to my Node Server and pass it through the Twitter API?
In this way I will have to just store the AWS S3 image link to my MongoDB and get rid of a big string data.
API
// THREAD SCHEDULER API
app.post('/TweetThread/:id', async (req, res) => {
const ID = req.params.id;
const { texts, dateTimeGMT } = req.body;
const filter = { _id: ObjectId(ID) };
const findUser = await userCollection.findOne(filter);
// GET TIMEZONE FROM INSTANT REQ
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const threadSchData = {
texts,
date: new Date(dateTimeGMT).toLocaleDateString(),
time: new Date(dateTimeGMT).toLocaleTimeString(),
timezone: timeZone,
token: findUser.token,
token_secret: findUser.token_secret,
screen_name: findUser.screen_api
}
const result = await threadDataCollection.insertOne(threadSchData);
res.json(result);
});
Scheduler
// TWITTER THREAD SCHEDULER
const threadSch = cron.schedule('*/1 * * * *', async () => {
const cursor = threadDataCollection.find({});
const threadsArray = await cursor.toArray();
// console.log(threadsArray);
threadsArray.forEach(thread => {
// Twitter Thread CONFIG
const configThread = {
consumer_key: process.env.CONSUMER_KEY,
consumer_secret: process.env.CONSUMER_SECRET,
access_token: thread.token,
access_token_secret: thread.token_secret
};
// INSERTING THREAD DATA TO THREAD FUNCTION
async function tweetThread() {
const t = new TwitThread(configThread);
await t.tweetThread(thread.texts);
}
// Calculating The Time According to Time ZONE
let scheduledTime = new Date(thread.date + ' ' + thread.time);
let now = new Date();
let year = now.getFullYear();
let month = now.getMonth() + 1;
let day = now.getDate();
let hour = now.getHours();
let minute = now.getMinutes();
let new_date = new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + '00');
const countingTime = scheduledTime.toLocaleString("en-US", { timeZone: thread.timezone });
const serverTime = new_date.toLocaleString("en-US", { timeZone: thread.timezone });
// POSTING THREAD WHEN TIME MATCHED
if (countingTime === serverTime) {
tweetThread();
console.log('Posted Thread Once');
console.log('TRUE');
}
});
});
threadSch.start();
This is the request body where in media_data field I'm passing the string data from front-end
you need credentials to connect to aws from command line. Then you have only to run from the image path aws s3 cp your_file_name s3:\\your_bucket_name\your_file_name .
Then save this your_file_name to MongoDB and upload it from here. There are more tricks to use cloudformation and to make s3 public so you can only point to the file from your html page. If you need help with any of the steps please write me.
Hello im trying to query my mongoDB collection to find all data from specific date.
For some reason when I use Find() with the object specified as param in the call it works
but when I try to declare a variable it doesnt .... can some explain me why?
this doesnt work
//Convert Date to short Date string
let day = foundRapport.date.getUTCDate();
let fullMonth = foundRapport.date.getMonth() + 1;
let year = foundRapport.date.getFullYear();
let date = `${day}/${fullMonth}/${year}`;
//query for Date_Travail
let query = {};
let criteria = "Date_Travail";
query[criteria] = date;
console.log(query); // this returns { Date_Travail: '24/7/2020' }
//Find data with query as param
Heures.find(query, (err, foundHours) => {
if (err) {
console.log(err);
} else {
res.render("rapportDetail", {
rapport: foundRapport,
shortDate: date,
hours: foundHours,
});
}
});
But this here does....
//Convert Date to short Date string
let day = foundRapport.date.getUTCDate();
let fullMonth = foundRapport.date.getMonth() + 1;
let year = foundRapport.date.getFullYear();
let date = `${day}/${fullMonth}/${year}`;
// let query = {};
// let criteria = "Date_Travail";
// query[criteria] = date;
// console.log(query);
//Find data with object as param
Heures.find({Date_Travail: "24/07/2020"}, (err, foundHours) => {
if (err) {
console.log(err);
} else {
res.render("rapportDetail", {
rapport: foundRapport,
shortDate: date,
hours: foundHours,
});
}
});
can anyone point me on the direction of why?
Thanks
I want to create a script which is taking the average of the Volume for last 7(for example) days.
I'm stuck with aggregation stages since first stage I need to take Date for last 7 days and in second stage calculate Average of Volume
Package list:
Node-schedule - */1 * * * * (Runs the script every minute)
Binance API - Taking data from them.
Screenshot for showcasing how the document looks like in MongoDB.
Aggregation part of the Code.
const average = await dbo.collection(symbol).aggregate([{
'$match': {
'Date': { '$gte': new Date((new Date().getTime() - (7 * 24 * 60 * 60 * 1000))) }
},
},
{
'$group': {
_id: null,
'Volume': { '$avg': '$Volume' }
},
}
]).toArray();
This code returns me an empty array in terminal like this > []
Full Code here.
const { MongoClient } = require('mongodb');
const schedule = require('node-schedule');
const fetch = require("node-fetch");
const symbols = ["ADABTC", "AEBTC", "AIONBTC", "ALGOBTC", "ARDRBTC"];
//a descriptive name helps your future self and others understand code easier
const getBTCData = async symbol => { //make this function accept the current symbol
//async/await lets us write this much nicer and with less nested indents
let data = await fetch(`https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=30m&limit=1`).then(res => res.json());
const btcusdtdata = data.map(d => {
return {
Open: parseFloat(d[1]),
High: parseFloat(d[2]),
Low: parseFloat(d[3]),
Close: parseFloat(d[4]),
Volume: parseFloat(d[5]),
Timespan: 30,
}
});
console.log(btcusdtdata);
saveToDatebase(symbol, btcusdtdata);
//recursive functions are complicated, we can get rid of it here
//by moving the responsibility to the caller
};
//helper function for an awaitable timeout
const sleep = ms => new Promise(res => setTimeout(res, ms));
const j = schedule.scheduleJob('*/1 * * * *', async() => {
//expand this function to be responsible for looping the data
for (let symbol of symbols) {
//we can pass symbol to getBTCData instead of making it
//responsible for figuring out which symbol it should get
await getBTCData(symbol);
await sleep(8000);
}
});
//make this a helper function so `saveToDatabase()` isn't also responsible for it
const getDateTime = () => {
let today = new Date();
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return date + ' ' + time;
};
const saveToDatebase = async(symbol, BTCdata) => {
try {
const url = 'mongodb://username:password#ipadress:port/dbname';
let dateTime = getDateTime();
let db = await MongoClient.connect(url, { useUnifiedTopology: true });
const dbo = db.db('Crypto');
const myobj = Object.assign({ Name: symbol, Date: dateTime }, BTCdata[0]);
await dbo.collection(symbol).insertOne(myobj);
const average = await dbo.collection(symbol).aggregate([{
'$match': {
'Date': { '$gte': new Date((new Date().getTime() - (7 * 24 * 60 * 60 * 1000))) }
},
},
{
'$group': {
_id: null,
'Volume': { '$avg': '$Volume' }
},
}
]).toArray();
console.log('1 document inserted');
console.log(average);
db.close();
} catch (e) {
console.error(e)
}
};
EDIT1
If I delete $match part my script is working and I receive average of Volume.
Screenshot of terminal after success try without $match
EDIT2
According to the last answer I understand that I need to change Date format from string to object, but I really can't get how I can do it in this part?
const getDateTime = () => {
let today = new Date();
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return date + ' ' + time;
};
EDIT3
After editing the Date format I receive a Document in MongoDB in strange Date format like - Date:2020-07-20T13:24:02.390+00:00
Code here:
const getDateTime = () => {
let today = new Date();
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return new Date();
};
The problem is on the Date field format.
The getDateTime function returns a string so Mongo is managing the field as a string not as a Date object so the $gte check will compare string not dates.
You should change the function to getDateTime = () => new Date(). Mongo will manage the date correctly storing in UTF Timezone.
Tring to query a date-string in the $match field would be really difficult.
Edit:
To update the typing just:
const getDateTime = () => {
return new Date();
};
How to get the total number of records for the current day? I get 0 as a result, although I have a couple of entries.
module.exports.getOnline = async function (req, res) {
try {
var current_date = new Date().toISOString()
const online = await Online.find({ Date: current_date })
res.status(200).json(online.length)
} catch (e) {
errorHandler(res, e)
}
}
I think that currently you are searching for records with a specific date and time. Try to look for a range of dates, with today at 00:00 and today at 23:59.
This one might help:
https://stackoverflow.com/a/2943685/12647796
edit - I tried to match it to your problem
var min_date = new Date();
var max_date = new Date();
min_date.setHours(0,0,0,0);
max_date.setHours(23,59,59,999);
const online = await Online.find({
Date: {
$gte: min_date,
$lt: max_date
}
})
res.status(200).json(online.length)
var current_date = new Date().toISOString()
The toISOString() method converts a Date object into a string, using the ISO standard.
The standard is called ISO-8601 and the format is: YYYY-MM-DDTHH:mm:ss.sssZ
so when you get the current date and using this method it will not match with the existing records in database.that's why query return 0.
if you want to get the current day records you need to use following code for getting current date,month and year than use it for query.
module.exports.getOnline = async function (req, res) {
try {
var d = new Date();
var date = d.getDate();
var month = d.getMonth() + 1; // Since getMonth() returns month from 0-11 not 1-12
var year = d.getFullYear();
var dateStr = date + "/" + month + "/" + year;
const online = await Online.find({ Date: dateStr })
res.status(200).json(online.length)
} catch (e) {
errorHandler(res, e)
}
}
I think this will help you.
I´m quite new with Node.js and MongoDB and I`m having trouble when build queries.
For example I want to filter the date of my object depending on the request. This is what I did:
var startDate = req.body.startDate;
var endDate = req.body.endDate;
let findParams = {
userId:req.userId
};
if(startDate){
findParams["start"] = { $gt: new Date(startDate)};
}
if(endDate){
findParams["start"] = { $lt: new Date(endDate)};
}
if(startDate && endDate){
findParams["start"] = { $gt: new Date(startDate),$lt: new Date(endDate)};
}
console.log(findParams);
WorkTime.find(findParams)
I have to build the "start" param every time depending on what the user sends. If the user sends both values (startDate & endDate) I have to build the params object again.
What would be the optimal way to build this query?
Thanks in advance!
You code is fine. There is no any "optimal" way, but a bit "elegant"
try {
var startDate = req.body.startDate;
var endDate = req.body.endDate;
let findParams = {
userId: req.userId
};
if (startDate || endDate) {
findParams["start"] = { };
if (startDate) {
findParams["start"]["$gt"] = new Date(startDate);
}
if (endDate) {
findParams["start"]["$lt"] = new Date(endDate);
}
}
console.log(findParams);
WorkTime.find(findParams)
} (catch e) {
console.log("Error occured: " + e);
}