I am trying to do a query between dates. In compass I can do the query without any problem using the native function ISODate(). But when trying in my code I can't import that function, and new Date() is not warking.
Documents as example:
let trxs = [{
_id:612e112f7a7eaa7a5c1fd0d3
created:2021-09-31T11:23:25.184+00:00
amount:19.98
user:"612e112f7a7eaa7a5c1fd0d1"
type:"deposit"
},
{
_id:612e112f7a7eaa7a5c1fd0d6
created:2021-09-31T11:23:25.184+00:00
amount:10
user:"612e112f7a7eaa7a5c1fd0d4"
type:"deposit"
}
]
Query
let trxs = await Transaction.aggregate([
{
$match: {
type: req.query.type,
$and: [
{
created:
{
$gt: new Date(new Date().setHours(0, 0, 0))
},
},
{
created:
{
$lt:new Date(new Date().setHours(23, 59, 59))
}
}
]
}
}, {
$group: {
_id: null,
amount: {
$sum: '$amount'
}
}
}
]);
//More info:
console.log(new Date(new Date().setHours(0, 0, 0))) // 2021-08-31T22:00:00.953Z
console.log(new Date(new Date().setHours(23, 59, 59))) // 2021-09-01T21:59:59.952Z
//Error
ReferenceError: amount is not defined
I tried to import ISODate function but I don't find the way to do it.
Try the moment.js library. There is no need for $and: []
{
$match: {
type: req.query.type,
created: {
$gt: moment().startOf('day').toDate(),
$lt: moment().endOf('day').toDate(),
}
}
}
Related
I have a big mongodb query that has some dynamic properties based on filter options, and including filtering between dates. My query is currently causing scanned Objects / returned results ratio to go above 1000. I am sure my query can be improved as well as adding suitable indexes but I am not sure of the correct index's / improvements to my query.
const userFilter = user ? { assignee: new Types.ObjectId(user) } : null;
const clientFilter = client ? { client: new Types.ObjectId(client) } : null;
Collection.aggregate([
{
$match: {
...userFilter,
...clientFilter,
status: 1,
customer: new Types.ObjectId(customer),
},
},
{
$match: {
$or: [
{
end: {
$gte: new Date(end),
},
start: {
$lte: new Date(start),
},
},
{
end: {
$gte: new Date(end),
},
start: {
$lte: new Date(end),
$gte: new Date(start),
},
},
{
start: {
$lte: new Date(start),
},
end: {
$lte: new Date(end),
$gte: new Date(start),
},
},
{
start: {
$gte: new Date(start),
},
end: {
$lte: new Date(end),
},
},
{
start: {
$lte: new Date(end),
},
// #ts-ignore
start: {
$gte: new Date(start),
},
},
{
end: {
$lte: new Date(end),
},
// #ts-ignore
end: {
$gte: new Date(start),
},
},
],
},
},
{
$sort: { createdAt: 1 },
},
}
Depending on filter options we could be filtering by assignee and/or client.
We also only want returned results where the start or end date of the document falls within the start and end date filters.
I have tried a few variations of the query itself, as well as adding some compound indexes but had no real success improving the query or index's.
This is not an answer, but a bit too long for a comment:
Do you really like conditions like
{
$match: {
null,
null,
status: 1,
customer: new Types.ObjectId(customer),
},
}
Or should you better use:
let match = {
status: 1,
customer: new Types.ObjectId(customer)
};
if (user)
match.assignee = new Types.ObjectId(user);
if (client)
match.client = new Types.ObjectId(client);
Collection.aggregate([
{ $match: match },
...
I never tried, perhaps {$match: null} prevents any index use.
Hi I am trying the below query in my nodejs code
const totalCount = await model.countDocuments({
'createdAt': { $gte: new Date(startDate), $lte: new Date(endDate) },
}).exec();
const activeCount = await model.countDocuments({
'createdAt': { $gte: new Date(startDate), $lte: new Date(endDate) },
'enabled': true,
}).exec();
const inactiveCount = (totalCount - activeCount);
return { totalCount, activeCount, inactiveCount };
Is there any way i can combine the above in a single query using aggregate in mongoose? Kindly guide me to the best solution .
Yes, quite simple using some basic operators, like so:
model.aggregate([
{
$match: {
createdAt: {
$gte: new Date(startDate),
$lte: new Date(endDate)
}
}
},
{
$group: {
_id: null,
totalCount: {
$sum: 1
},
activeCount: {
$sum: {
$cond: [
{
$eq: [
"$enabled",
true
]
},
1,
0
]
}
}
}
},
{
$project: {
_id: 0,
totalCount: 1,
activeCount: 1,
inactiveCount: {
$subtract: [
"$totalCount",
"$activeCount"
]
}
}
}
])
Mongo Playground
I'm trying to make a query in my javascript code, when I try to execute the query it in robo3t it works, but when I try it in my angular code, it doesn't can you please help me?
Here is the code in robo3t.
db.getCollection('interviews').aggregate({
$match: {
status: {
$ne: 'Callback'
},
dateInserted: {
$gte: ISODate("2019-02-07 00:00:00"),
$lte: ISODate("2019-02-08 00:00:00")
},
'insertedBy.adminId': '5c353f840fe0fd000440df01'
}
},
{
$group: {
_id: {
insertedBy: '$insertedBy.email'
},
timeExported: {$first: '$dateInserted'},
total: {
$sum: 1
}
},
},
{
$limit: 100
}
)
and the result shows:
result image
Now here is my code in angular
query = [{
$match: {
status: {
$ne: 'Callback'
},
dateInserted: {
$gte: new Date("2019-02-07 00:00:00").toISOString(),
$lte: new Date("2019-02-08 00:00:00").toISOString()
},
'insertedBy.adminId': localStorage.getItem('_lgu_')
}
},
{
$group: {
_id: {
insertedBy: '$insertedBy.email'
},
timeExported: {$last: '$dateInserted'},
total: {
$sum: 1
}
},
},
{
$limit: 100
},
{
$sort: {
total: 1
}
}
]
Now when I try the query in angular, it doesn't give any result and when I remove the date condition:
dateInserted: {
$gte: new Date("2019-02-07 00:00:00").toISOString(),
$lte: new Date("2019-02-08 00:00:00").toISOString()
},
It will give a result but not what I am expecting.
i am new in node js i need to find data daily,
weekly and monthly but i don't know how to do this?
currently i am finding today data . also need to find current week data and current month data.
i don't have idea how to do this, can you please help.
exports.getData = function(req,res)
{
getMyData().then(function(data){
res.status(200).json({
msg:'true',
data: data
});
}).catch(function(err){
res.status(401).json({
msg:'Not Logged In',
error: err
});
});
function getMyData(){
return new Promise(function(resolve,reject){
var token = req.headers['x-access-token'];
if (!token)
return reject({'msg':'No Token'});
jwt.verify(token,config.secret,function(err,decode){
if(err)
{
reject({'msg':'Failed to authenticate token.'});
}
else{
var start = new Date();
start.setHours(0,0,0,0);
var end = new Date();
end.setHours(23,59,59,999);
Data.find({userId: decode.id,created: {$gte: start, $lt: end}},function(err,data){
if(err){
reject(err);
}
else
{
resolve(data);
}
});
}
});
});
}
}
here is my schema
var DataSchema = new Schema({
userId: {
type: String,
required: 'Kindly enter your Report'
},data: {
type: String,
required: 'Kindly enter your Report'
},
created:{
type:Date,
default:Date.now
}
});
You can call find query based on different conditions from node.js.
async function getMyData() {
var token = req.headers['x-access-token'];
if (!token)
throw {
'msg': 'No Token'
};
jwt.verify(token, config.secret, function (err, decode) {
if (err) {
throw err;
} else {
let today = new Date();
today.setHours(0, 0, 0, 0)
let first = today.getDate() - today.getDay();
let last = first + 6;
let firstday = new Date(today.setDate(first)).toUTCString();
let lastday = new Date(today.setDate(last)).toUTCString();
let firstDayMonth = new Date(today.setDate(1));
let lastDayMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0)
lastDayMonth.setHours(23, 59, 59, 0);
today = new Date().setHours(0, 0, 0, 0);
return await Promise.all([
Data.find({
userId: decode.id,
created: {
$gte: today
}
}).exec(),
Data.find({
userId: decode.id,
created: {
$gte: firstday,
$lte: lastday
}
}).exec(),
Data.find({
userId: decode.id,
created: {
$gte: firstDayMonth,
$lte: lastDayMonth
}
}).exec()
]);
}
});
}
MongoDB Aggregate query : only problem I'm seeing is $cond else block returns "". That you can handle in node js.
var today = new Date().setHours(0, 0, 0, 0);
var first = today.getDate() - today.getDay();
var firstDayWeek = new Date(today.setDate(first));
var lastDayWeek = new Date(today.setDate(first + 6));
var firstDayMonth = new Date(today.setDate(1));
var lastDayMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0)
lastDayWeek.setHours(23, 59, 59, 0);
lastDayMonth.setHours(23, 59, 59, 0);
today = new Date().setHours(0, 0, 0, 0);
db.getCollection('TEST').aggregate([{
$match: {
userId: decode.id
}
}, {
$group: {
"_id": "",
"today": {
$push: {
$cond: {
if: {
$gte: ["$created", new Date(today)]
},
then: "$$ROOT",
else: ''
}
}
},
"week": {
$push: {
$cond: [{
$and: [{
$gte: ["$created", new Date(firstDayWeek)]
},
{
$lte: ["$created", new Date(lastDayWeek)]
}
]
},
"$$ROOT",
''
]
}
},
"month": {
$push: {
$cond: [{
$and: [{
$gte: ["$created", new Date(firstDayMonth)]
},
{
$lte: ["$created", new Date(lastDayMonth)]
}
]
},
"$$ROOT",
''
]
}
}
}
}])
//If you want to filter in mongo query
.forEach(function (data) {
data.today = data.today.filter(e => e != "")
data.week = data.week.filter(e => e != "")
print(data);
})
Output
{
"_id": "",
"today": [{
"_id": ObjectId("5aaa2605d52a86d42a362479"),
"created": ISODate("2018-03-15T07:51:33.014Z")
}
],
"week": [{
"_id": ObjectId("5aaa2605d52a86d42a362479"),
"created": ISODate("2018-03-15T07:51:33.014Z")
},
{
"_id": ObjectId("5aaa2606d52a86d42a36247a"),
"created": ISODate("2018-03-13T07:51:34.702Z")
}
],
"month": [{
"_id": ObjectId("5aaa2605d52a86d42a362479"),
"created": ISODate("2018-03-15T07:51:33.014Z")
},
{
"_id": ObjectId("5aaa2606d52a86d42a36247a"),
"created": ISODate("2018-03-13T07:51:34.702Z")
},
{
"_id": ObjectId("5aaa262ad52a86d42a36247b"),
"created": ISODate("2018-03-01T07:52:10.175Z")
}
]
}
My application needs to get the result of this query (this is already giving the correct result in mongoDb):
var denominator = db.getCollection('Transactions').aggregate({
$group: {
"_id": null,
"Alltotal": {$sum:"$transAmount"}
}
};
db.getCollection('Transactions').aggregate([{
$group: {
_id: '$merchantCode',
total: {
$sum: { $multiply: ['$transAmount', 100 ]}
}}},
{ $project: {
percentage: {
$divide: [
"$total",
denominator.toArray()[0].Alltotal
]
}
}
}
])
Now here is how I am trying to execute it:
var express = require('express');
var app = express();
var mongojs = require('mongojs');
var dbTransaction = mongojs('dataAnalysisDb',['Transactions']);
app.get('/Transactions',function(req,res){
var denominator = dbTransaction.Transactions.aggregate([{
$group: {
_id: 'null',
total: { $sum: '$transAmount' }
}
}]);
dbTransaction.Transactions.aggregate([{
$group: {
_id: '$mtype',
total: {
$sum: { $multiply: ['$transAmount', 100 ]}
}}},
{ $project: {
percentage: {
$divide: [
"$total",
denominator.toArray()[0].total
]
}
}
},
{ $sort : { _id : 1, posts: 1 } }
], function(err,docs){
console.log(docs); //this is for testing
res.json(docs);
});
});
I think this is not working because I am not sending the variable in the correct way to the server and when I use it on the operation it is not defined. I will appreciate any suggestion on how to fix it.
Thank you
I found a way to solve it and it might not be the best but it worked, I leave it here for whoever else needs it
var denominator = dbTransaction.Transactions.aggregate([{
$group: {
"_id": null,
"Alltotal": {$sum:"$transAmount"}
}}]).toArray(function(err,items){
console.log(items[0].Alltotal); //this is for testiong
dbTransaction.Transactions.aggregate([{
$group: {
_id: '$mtype',
total: {
$sum: { $multiply: ['$transAmount', 100 ]}
}}},
{ $project: {
percentage: {
$divide: [
"$total",
items[0].Alltotal
]
}
}
},
{ $sort : { _id : 1, posts: 1 } }
],function(err,docs){
console.log(docs); //this is for testing
res.json(docs);
});
});