NodeJS (Express) + MongoDB + Angular stream a request - node.js

I want to stream a MongoDB query in NodeJS because, in Angular, i have a chart and i want to update the data without making a refresh.
So far, this is my code (NodeJS):
exports.gettoday = function (request, response) {
db.collection("nifi5", function (err, collection) {
collection
.aggregate([
{
$group: {
_id: {
minute: {
$minute: { $dateFromString: { dateString: "$created_at" } },
},
hour: {
$hour: { $dateFromString: { dateString: "$created_at" } },
},
day: {
$dayOfMonth: { $dateFromString: { dateString: "$created_at" } },
},
month: {
$month: { $dateFromString: { dateString: "$created_at" } },
},
year: {
$year: { $dateFromString: { dateString: "$created_at" } },
},
},
avg: { $avg: "$value_temperature" },
},
},
])
.stream()
.toArray(function (err, items) {
if (err) {
response.statusMessage = {
devMessage: err,
clientMessage: "Unexpected error, try again latter",
};
response.send(response.statusMessage).end();
}
let tarray = { labels: [], data: [] };
items.forEach((element) => {
element.date = element._id.hour + ":" + element._id.minute;
element.avg = Math.round(element.avg * 100) / 100;
});
items.sort(function (a, b) {
return a.date < b.date ? -1 : 1;
});
items.forEach((element) => {
tarray.labels.push(element.date);
tarray.data.push(element.avg);
});
return response.json(tarray);
});
});
};
Angular:
gettodaydata(): Observable<any> {
return this.http.get(`${environment.baseURL}gettoday`).subscribe((data) => {
this.data_line.push(...data.data);
this.labels_line.push(...data.labels);
this.isLineChartLoading = false;
});
}
Can u please help me streaming this controller and fetch the data in Angular to update my chart when new data comes do my database ?
Thank you all!

You should give a try to socket.io, it creates a persistent connection and responds to events in real time.

Related

MongoDb aggregation for daily number of views and downloads

const fetchSummary = expressAsyncHandler(async (req, res) => {
//GET DAILY SUMMARY
const dailySummary = await Post.aggregate([
{
$group: {
_id: { $dateToString: { format: "%Y-%m-%d", date: "$createdAt" } },
downloads: { $sum: "$downloadCount" },
totalViews: { $sum: "$numViews" },
},
},
{ $sort: { _id: -1 } },
]);
res.send({ dailySummary });
});
Can someone please help me out here, I'm trying to fetch sum total for daily views and downloads for a post
And here is my result
"dailySummary": [
{
"_id": "2023-01-07",
"downloads": 49,
"totalViews": 227
},
{
"_id": "2023-01-06",
"downloads": 41,
"totalViews": 605
},
{
"_id": "2023-01-05",
"downloads": 0,
"totalViews": 0
}
],
And this result is a wrong
number of views for today is not even up 40,and downloads 10
//============
// Fetch single Post
//============
const fetchPostCtrl = expressAsyncHandler(async (req, res) => {
const { id } = req.params;
validateMongodbId(id);
try {
const post = await Post.findById(id).populate("user comments");
//Updating Number of views
await Post.findByIdAndUpdate(
id,
{
$inc: { numViews: 1 },
},
{ new: true }
);
res.json(post);
} catch (error) {
res.json(error);
}
});
This is how I'm fetching post details

findOneAndUpdate not returning new document in loopback

I am working with loopback mongodb. Here is my query
const counter = await db.collection("counters").findOneAndUpdate(
{ prefix: "C" },
{ $inc: { sequence_value: 1 } },
{ projection: { "sequence_value" : 1 }, returnNewDocument: true }
);
It returns
{
lastErrorObject: { n: 1, updatedExisting: true },
value: { _id: 'customerid', sequence_value: 590 },
ok: 1
}
So I have two questions here.
Why it is not returning new document here? I am always getting old sequence_value.
What is lastErrorobject and ok? I only need the document object like this { _id: 'customerid', sequence_value: 590 }
const getCounter = () => new Promise((resolve, reject) => {
db.collection("counters").findOneAndUpdate(
{ prefix: "C" },
{ $inc: { sequence_value: 1 } },
{ projection: { "sequence_value" : 1 }, returnNewDocument: true },
(err, result) => {
if (err) { return reject(err); }
resolve(result);
},
);
});
const counter = await getCounter();

How to get data from mongodb between including two days in mongodb using mongoose

Tried to get records from mongodb between including two days but in my code only i am getting between two days.
Example:
01-06-2020 to 08-06-2020 = getting records from 02-06-2020 to 08-06-2020(01-06-2020 missing)
But i want 01-06-2020 to 08-06-2020 = need to get records from 01-06-2020 to 08-06-2020.
How to get it?
Mongodb Data:
{
_id:ObjectId("5edd1df67b272e2d4cf36f70"),
pname:"Test 1",
category:"Choco 1",
todaydate:2020-06-01T18:30:00.000+00:00
},
{
_id:ObjectId("5gdd1df67b272e2d4cf36f72"),
pname:"Test 2",
category:"Choco 3",
todaydate: 2020-06-02T18:30:00.000+00:00
},
{
_id:ObjectId("5kdd1df67b272e2d4cf36f74"),
pname:"Test 5",
category:"Choco 6",
todaydate: 2020-05-01T18:30:00.000+00:00
},
{
_id:ObjectId("5ewd1df67b272e2d4cf36f75"),
pname:"Test 6",
category:"Choco 8",
todaydate: 2020-06-03T18:30:00.000+00:00
},
{
_id:ObjectId("5sdd1df67b272e2d4cf36f76"),
pname:"Test 3",
category:"Choco 9",
todaydate: 2020-06-04T18:30:00.000+00:00
},
{
_id:ObjectId("5tdd1df67b272e2d4cf36f78"),
pname:"Test 11",
category:"Choco 10",
todaydate: 2020-06-05T18:30:00.000+00:00
}
data.model.js:
const mongoose = require('mongoose');
var userSchemaDate = new mongoose.Schema({
pname: {
type: String
},
category: {
type: String
},
todaydate: {
type: Date
}
}, {
versionKey: false,
collection: 'data'
});
module.exports = mongoose.model('Data', userSchemaDate);
data.controller.js:
module.exports.getReportTableData = (req, res, next) => {
var collection = req.query.collection;
let tableReportdata = dbc.model(collection);
let date1 = "01-06-2020"; dd/mm/yyyy
let date2 = "07-06-2020"; dd/mm/yyyy
tableReportdata.find({
$and: [{
todaydate: {
$gt: date1
}
},
{
todaydate: {
$lt: date2
}
}
]
}, function(err, docs) {
if (err) {
console.log(err);
return;
} else {
console.log("Successful loaded report data");
res.json({ data: docs, msg: 'Report data loaded.' });
}
});
}
The answer on your other question should return the correct result. I'll also emphasise that it's better to store the date as date object.
Let's try another approach by using $dateFromString on the input values as well.
tableReportdata.find({
$expr: {
$and: [
{
$gte: [
{
$dateFromString: {
dateString: "$todaydate",
format: "%d-%m-%Y",
timezone: "UTC"
}
},
{
$dateFromString: {
dateString: "01-06-2020",
format: "%d-%m-%Y",
timezone: "UTC"
}
}
]
},
{
$lte: [
{
$dateFromString: {
dateString: "$todaydate",
format: "%d-%m-%Y",
timezone: "UTC"
}
},
{
$dateFromString: {
dateString: "07-06-2020",
format: "%d-%m-%Y",
timezone: "UTC"
}
}
]
}
]
}
}, function(err, docs) {
if (err) {
console.log(err);
return;
} else {
console.log("Successful loaded report data");
res.json({ data: docs, msg: 'Report data loaded.' });
}
});
Shorter version with a helper function
const dateUTCexpr = (dateString) => ({
$dateFromString: {
dateString,
format: "%d-%m-%Y",
timezone: "UTC"
}
})
tableReportdata.find({
$expr: {
$and: [
{
$gte: [dateUTCexpr("$todaydate"), dateUTCexpr("01-06-2020")]
},
{
$lte: [dateUTCexpr("$todaydate"), dateUTCexpr("07-06-2020")]
}
]
}
}, function(err, docs) {
if (err) {
console.log(err);
return;
} else {
console.log("Successful loaded report data");
res.json({ data: docs, msg: 'Report data loaded.' });
}
});
If you have todaydate defined as String in your schema, also make sure that it's properly converted in your database, you can use the following code
const dateUTCexpr = (dateString) => ({
$dateFromString: {
dateString,
format: "%d-%m-%Y",
timezone: "UTC"
}
})
tableReportdata.find({
todaydate: {
$gte: dateUTCexpr("01-06-2020"),
$lte: dateUTCexpr("07-06-2020")
}
}, function(err, docs) {
if (err) {
console.log(err);
return;
} else {
console.log("Successful loaded report data");
res.json({ data: docs, msg: 'Report data loaded.' });
}
});

MongoDB findOneAndUpdate Updates But Nothing Changes

I have a cluster on atlas. My current object seems like below:
{
"_id": {
"$oid":"5e9d8ccfb3d80e3824bf856c"
},
"user": {
"name":"test",
"channelGroups": [
{
"active": true,
"name": "an example of test",
"creationDate": "20 Apr 2020 at 13:35 PM",
"summary": "an example summary",
"channels": []
}
]
},
"__v": {
"$numberInt":"0"
}
}
Here is my controller method: ( I use mongoose with express )
createANewChannel: (req, res) => {
channelGroupModel.findOneAndUpdate({
"user.name": "test", "user.channelGroups": {
$elemMatch: {
"name": "an example of test" // req.params.slug
}
}
}, { $push: {
"channelGroups.channels": {
filter: {
keyword: "#example",
keywordType: "hashtag",
active: true,
fetchFrequency: 1,
},
tweets: []
}
}
},
(error, success) => {
if (error) {
console.log(error);
} else {
console.log(success);
}
}
);
res.send('ok');
},
Problem:
I want to push a new channel object into the channelGroups array according to channelGroups' name value. My code works but nothing happens.
=====================================================================
Updated working version:
channelGroupModel.findOneAndUpdate(
{
"user.name": "test"
},
{
$push: {
"user.channelGroups.$[elem].channels": {
filter: {
keyword: "#example",
keywordType: "hashtag",
active: true,
fetchFrequency: 1,
},
tweets: []
}
}
},
{
arrayFilters: [{"elem.name": "an example of test"}]
},
(error, success) => {
if (error) {
console.log(error);
} else {
console.log(success);
}
}
)
You want to use arrayFilters:
channelGroupModel.findOneAndUpdate(
{
"user.name": "test"
},
{
$push: {
"channelGroups.$[elem].channels": {
filter: {
keyword: "#example",
keywordType: "hashtag",
active: true,
fetchFrequency: 1,
},
tweets: []
}
}
},
{
arrayFilters: [{"elem.name": "an example of test"}]
},
(error, success) => {
if (error) {
console.log(error);
} else {
console.log(success);
}
}
)
Just FYI mongoose has a notorious bug on certain versions when it comes to arrayFilters.

How to improve the query performance it taking 30 sec to execute the query MongoDb

I am using node is along with mongoose.while I am executing this query its taking 30+ sec for execution
I think its due to looping how to improve the performance can anyone guide me I am new to mongoose
companies
.findById(
{
_id: companyProfile,
},
function(err, company) {
if (err) {
return res.status(400).send({
message: "Some Error Occured!",
});
} else {
var responseJson = [];
company.ambulances.forEach(function(doc) {
Gps.find({
$and: [
{
device: doc.deviceId,
},
{
longitude: {
$exists: true,
$ne: "",
},
},
{
locationDate: {
$exists: true,
$ne: "",
},
},
{
latitude: {
$exists: true,
$ne: "",
},
},
],
})
.sort({
$natural: -1,
})
.limit(1)
.exec(function(err, gpsLocations) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err),
});
} else {
responseJson.push({
gps: gpsLocations,
});
if (
company.ambulances.length === responseJson.length
) {
res.json(responseJson);
}
}
});
});
}
},
)
.populate("ambulances");
Well, first try to convert the callbacks to Promises, in order the code to be easier to understand. Now about the speed, you can match all the Gps objects using the $in operator. So the result will be something like that.
try {
const company = await companies.findById({ _id: companyProfile });
const gpsLocations = await Gps.find({
$and: [
{
device: { $in: company.ambulances },
},
{
longitude: {
$exists: true,
$ne: "",
},
},
{
locationDate: {
$exists: true,
$ne: "",
},
},
{
latitude: {
$exists: true,
$ne: "",
},
},
]
}).sort({
$natural: -1,
}).populate("ambulances");
return res.json(gpsLocations.map(gpsLocation => ({
gps: gpsLocation,
})));
} catch(e) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err),
});
}

Resources