Query with string date format in mongodb - node.js

I have a data like below in my mongoDB collection. I want to count the total number or search_term on today basis.
_id:ObjectId("5b7e1d38981cdc1a7c8bb5fc")
search_term:"Baiyoke Boutique"
date:"August 23rd 2018, 9:34:32 am"
_id:ObjectId("5b7e1fa8fa27fd2754080ad9")
search_term:"Baiyoke Boutique"
date:"August 23rd 2018, 9:44:56 am"
_id:ObjectId("5b7e28314d2d0f388c1596cd")
search_term:"Baiyoke Florting Market"
date:"August 23rd 2018, 10:21:21 am"
I have tried following query. I have used moment. I am not what mistake I did.
var start = moment().startOf('day');
var end = moment().endOf('day');
history.find({
date: {
$gte: start,
$lt: end
}
}).count().toArray(
function (e, res) {
if (e) callback(e)
else callback(null, res)
});

You can try below queries in mongodb 3.6 and above
db.collection.find({
"$expr": {
"$gte": [{ "$dateFromString": { "dateString": "$date" }}, start.toDate() ],
"$lt": [{ "$dateFromString": { "dateString": "$date" }}, end.toDate() ]
}
}).count()
or with aggregation
db.collection.aggregate([
{ "$addFields": {
"date": {
"$dateFromString": {
"dateString": "$date"
}
}
}},
{ "$match": { "date": { "$gte": start.toDate(), "$lt": end.toDate() }}},
{ "$count": "count" }
])

You can try this
db.col.aggregate([{$addFields: {
convertedDate: { $toDate: "$date" }
}},
{"$match" :
{"convertedDate" :
{"$gte" : ISODate("2018-08-23T09:34:32.000Z"),
"$lte" : ISODate("2018-08-23T09:34:32.000Z")}
}
},
{"$group" : {"_id" : null,"count" : {"$sum" : 1}}},
{"$project" : {"_id" : 0}}
])
This is for Node js
var start = moment().startOf('day');
var end = moment().endOf('day');
history.aggregate([{
$addFields: {
convertedDate: { $toDate: "$date" }
}
},
{
"$match":
{
"convertedDate":
{
"$gte": start,
"$lte": end
}
}
},
{ "$group": { "_id": null, "count": { "$sum": 1 } } },
{ "$project": { "_id": 0 } }
], function (err, count) {
console.log(count)
})

Try:
history.count({date: {
$gte: start,
$lt: end
}}, function( err, count){
console.log( "Number of users:", count );
})
for native mongodb driver
db.collection(collectionName).count({}, function(error, numOfDocs){
if(error) return callback(error);
db.close();
callback(null, numOfDocs);
});

You are storing the string representation of the date. Try calling toDate() on moment object before storing into the database

Related

Selecting dates(mm-dd-yyyy) this month from mongodb

How can I select the dates from my mongodb for this month only, I have a date:{type:String} and my format is: mm-dd-yyyy ex: 09-03-2019:
Here is my router to get the distinct dates then count them, but not for monthly:
router.get('/blooddonationarea', function(req, res) {
sess=req.session;
Blooddonation.aggregate([{$group: {_id : "$date" , count :{$sum:1}}},{$sort: {_id: 1}}],function(err, date) {
res.json({ success: true, date: date });
});
});
yields to:
[ { _id: '04-11-2019', count6: 1 },
{ _id: '05-21-2019', count6: 1 },
{ _id: '10-11-2019', count6: 3 },
{ _id: '10-22-2019', count6: 1 } ]
My desired output is to display the dates for example where date = month.now() then it will only show months for 01-dd-yyyy only.
I tried this :
const startOfMonth = moment().startOf('month').format('MM-DD-YYYY')
const endOfMonth = moment().endOf('month').format('MM-DD-YYYY')
Blooddonation.aggregate([
{ "$match": {
"date": { "$gte": startOfMonth, "$lte": endOfMonth }
}},
{ "$group": { "_id": "$date", "count": { "$sum": 1 } } },
{ "$sort": { "_id": 1 } }],function(err, date) {
res.json({ success: true, date: date });
console.log("dates are" + date);
});
});
You can use moment library to get the desired format and then use $gte and $lte operator to get the data for the current month only
const moment = require('moment')
const startOfMonth = moment().startOf('month').format('MM-DD-YYYY')
const endOfMonth = moment().endOf('month').format('MM-DD-YYYY')
Blooddonation.aggregate([
{ "$match": {
"date": { "$gte": startOfMonth, "$lte": endOfMonth }
}}
{ "$group": { "_id": "$date", "count": { "$sum": 1 } } },
{ "$sort": { "_id": 1 } }
])

MongoDB $addToSet to deep nested array of object

Below is my data structure.
{
"_id" : "room1",
"members" : [
{
"_id" : "member1",
"name" : "Michael",
"payments" : [
{
"month": "2018/09"
"amount": "20"
}
]
},
]
}
I want to push below object to Michael's payments
{
"month": "2018/09",
"amount": "5000"
}
In this case, What I want to is overwrite object, because month: "2018/09" already exist. Like below :
{
"_id" : "room1",
"members" : [
{
"_id" : "member1",
"name" : "Michale",
"payments" : [
{
"month": "2018/09"
"amount": "5000"
}
]
},
]
}
And, In case when I want to push object that not exist same month in payments, I want to add this object to payments.
{
"month": "2018/10",
"amount": "2000"
}
So the expected result is
{
"_id" : "room1",
"members" : [
{
"_id" : "member1",
"payments" : [
{
"month": "2018/09"
"amount": "5000"
},
{
"month": "2018/10"
"amount": "2000"
}
]
},
]
}
I tried like below, but it's not working. My code generate duplicated new month object every time I tried. How can I do this properly?
Rooms.update(
{
_id: "room1",
"members._id": "member1",
"members.$.payments": {
$not: {
$elemMatch: {
month: req.body.month
}
}
}
},
{
$addToSet: {
"members.$.payments": {
month: req.body.month,
amount: req.body.value
}
}
},
{ multi: true }, function (err, result) {
console.log(result)
}
)
You can use below command to add without duplicity either in months or amount
Rooms.update(
{
_id: "room1",
"members._id": "member1"
},
{
$addToSet: {
"members.$.payments": {
month: req.body.month,
amount: req.body.value
}
}
},function (err, result) {
console.log(result)
}
)
So I heard I have to determine duplication myself, so below is my code... it's writing now.,,
So Finally this is my code
Clubs.findOne({
uid: req.params.club_id,
"members._id": mongoose.Types.ObjectId(req.params.member_uid)
}, function(err, club){
let member = club.members.filter(el => {
if(el._id.equals(req.params.member_uid)) return el
})
let duplicated = false;
member[0].payments.map(el => {
if(el.month === req.body.month) duplicated = true
})
if(duplicated){
Clubs.update(
{
uid: req.params.club_id,
"members._id": mongoose.Types.ObjectId(req.params.member_uid),
},
{
$set: {
["members.$.payments."+index+".amount"] : req.body.value
}
},
function (err, result, third) {
if (err) throw err
console.log('result')
console.log(result)
res.json({})
}
)
} else {
Clubs.update(
{
uid: req.params.club_id,
"members._id": mongoose.Types.ObjectId(req.params.member_uid),
},
{
$push: {
"members.$.payments" : {
month : req.body.month,
amount: req.body.value
}
}
},
function (err, result, third) {
if (err) throw err
console.log('result')
console.log(result)
res.json({})
}
)
}
})
Perhaps consider changing the structure of your nested array to an object? So change this
{
"payments": [{
"month": "2018/09"
"amount": "5000"
},
{
"month": "2018/10"
"amount": "2000"
}
]
}
to this:
{
"payments": {
"2018/09": "5000",
"2018/10": "2000"
}
}
Then you can do a simple update:
Rooms.update({
_id: "room1",
"members._id": "member1",
"members.payments": {
$exists: true
}
}, {
$set: {
"members.payments." + req.body.month: req.body.value
}
},
)

Getting error like "date is not defind" using nodejs with mogodb? datetime store as a timestamp in db

i am getting data using nodejs with MongoDB. I have objects in the MongoDB. and now I am going for the getting data using date wise and my datetime filed is a timestamp. and I want to get data from start date to end date using MongoDB.
must imp note i want to print date in the my expected op.
here I this is my objects =>
{
"_id" : ObjectId("595be16ee04602135828e25c"),
"Action" : "Comment",
"datetime" : 1507099928000 // 4th oct 2017 convert date just for info here write
},
{
"_id" : ObjectId("595be16ee04602135828e25c"),
"Action" : "Comment",
"datetime" : 1508139441716 // 16th oct 2017 convert date just for info here write
}
{
"_id" : ObjectId("595be16ee04602135828e25c"),
"Action" : "Comment",
"datetime" : 1508139441716 // 16th oct 2017 convert date just for info here write
}
{
"_id" : ObjectId("595be16ee04602135828e25c"),
"Action" : "Like",
"datetime" : 1508139441716 // 16th oct 2017 convert date just for info here write
},
this is my query =>
InstaAc.aggregate([
{
"$match": {
"_id": ObjectId("595be16ee04602135828e25c"),
"datetime": {
"$lte": 1508141028150, "$gte": 1507622568000
}
},
"Action": {
$in: ["Comment", "Like"]
}
},
{
"$addFields": {
"datetime": {
"$add": [new Date(0), "$datetime"]
}
}
},
{
"$group": {
"_id": {
"$dateToString": {
"format": "%d-%m-%Y",
"date": "datetime"
}
},
"commentcount": { $sum: { $cond: [{ $eq: ["Action", "Comment"] }, 1, 0] } },
"likecount": { $sum: { $cond: [{ $eq: ["Action", "Like"] }, 1, 0] } },
}
},
{
"$sort": {
"_id": 1
}
}
]).exec(function (err, data) {
if (err) {
console.log(err);
}
else {
console.log(data);
}
})
this is my query above and I am getting an error like this "date is not defined"
please, anyone, know how can fix this then please help me.
my excepted o/p =>
{ _id: '16-10-2017', commentcount: 2 ,likecount:1},
Before you run your query create a date object and use that object instead of new Date(0).
var myDate = new Date(0);
And in your query
"$addFields": {
"datetime": {
"$add": [myDate, "$datetime"]
}

Query on date or does not exist?

Trying to figure out if I can make this query work using mongoose and nodejs.
Product.find({
price: { $gt: 2, $lt: 3},
date: { $gt: new Date() || $exists: false}
}). exec(callback);
Does anyone know if it is possible to check if a date does not exist send it back or if the date is greater than today?
Thanks
Use $or:
Product.find({
"price": { "$gt": 2, "$lt": 3 },
"$or": [
{ "date": { "$gt": new Date() } },
{ "date": { "$exists": false } }
]
}). exec(callback);
All arguments are generally an implicit AND, so just like it is "price greater than 2 AND less than 3" you are saying in addition "AND the date is greater than this date OR date does not exist".
Just to spell out the logic in phrase form
With "multiple fields like this, THEN you actually use an $and
Product.find({
"$and": [
{ "price": { "$gt": 2, "$lt": 3 } },
{ "$or": [
{ "date1": { "$gt": new Date() } },
{ "date1": { "$exists": false } }
]},
{ "$or": [
{ "date2": { "$gt": new Date() } },
{ "date2": { "$exists": false } }
]}
]
}). exec(callback);

Find element in array using mongodb

I simply want to count the element in array based on the query. I tried the following command but not solved my problem.
I want to count the element whose TimeStamp is in between "2017-02-17T18:30:00.000Z and "2017-02-18T18:29:59.999Z" on DATA2 array, but it returns only 1.
CODE Executed:
CODE 1
db.ABC.aggregate([{
$match: {
$and: [{
DATA2: {
$exists: true
}
}, {
"DATA2.TimeStamp": {
$gte: require('../../modules/getDates').getFromDate(item),
$lte: require('../../modules/getDates').getToDate(item)
}
}, {
Client_id: "123" /*req.query.client_id*/
}]
}
}, {
$project: {
DATASiz: {
$size: "$DATA2"
},
"has bananas": {
$in: ["DATA2.$.TimeStamp"]
}
}
}], function(err, result) {
console.log(result)
callBack();
})
Code 2
db.abc.find({ $and:[{DATA2: {$exists: true}},{Client_id: "123"},{"DATA2": { $elemMatch: { TimeStamp: { $gte: require('../../modules/getDates').getFromDate(item), $lte: require('../../modules/getDates').getToDate(item) } } }}]
}, function(err, result) {
console.log(JSON.stringify(result))
callBack();
})
Code 3
//db.abc.find //also tried
db.abc.count({
$and: [{
DATA2: {
$exists: true
}
}, {
"DATA2.TimeStamp": {
$gte: require('../../modules/getDates').getFromDate(item),
$lte: require('../../modules/getDates').getToDate(item)
}
}, {
Client_id: "123" /*req.query.client_id*/
}]
},{
"DATA2.$":1
}, function(err, result) {
console.log(result)
callBack();
})
JSON Format:
{
"_id": {
"$oid": "57c7404985737e2c78fde6b3"
},
"ABC": "1304258470",
"Status": "Not Found",
"DATA1": [
{123},{123},{123}
],
"Remark": "Not Found",
"DATA2": [
{
"TimeStamp": "2017-02-18T09:01:43.060Z",
"NdrStatus": "Door Locked",
},
{
"TimeStamp": "2017-02-18T08:09:43.347Z",
"NdrStatus": "HOLD",
},
{
"TimeStamp": "2017-02-20T08:09:43.347Z",
"NdrStatus": "HOLD",
}
]
}
Result:
I am getting the first element of DATA2 using CODE 3 but I know that as per the query 2 elements are to return.
I expect 2 as in count.
Also used $unwind $redact
Thanks in advance.
You can use the $filter and $size operators for this:
var start = require('../../modules/getDates').getFromDate(item),
end = require('../../modules/getDates').getToDate(item);
db.ABC.aggregate([
{
"$match": {
"DATA2": { "$exists": true },
"DATA2.TimeStamp": { "$gte": start, "$lte": end },
"Client_id": "123"
}
},
{
"$project": {
"DATASiz": {
"$size": {
"$filter": {
"input": "$DATA2",
"as": "item",
"cond": {
"$and": [
{ "$gte": ["$$item.TimeStamp", start] },
{ "$lte": ["$$item.TimeStamp", end] }
]
}
}
}
}
}
}
], function(err, result) {
console.log(result);
callBack();
});

Resources