Mongoose how to count unique days in a month? - javascript

i am working on a problem where in my database there supposed to be multiple entries from day to day.
each entry includes a timestamp. the problem is im supposed to find how many days in each month a data has been entered.
ex: if a user sends a message every 2 days in may. my answer would be: "the user used the message function for 15 days in may".
now if the user sends 5 messages every 2 days in may. the answer would be still 15. im only counting the days the user has been using the app.
using this query:
model.find({
date: {
$gte: new Date(startOfMonth),
$lt: new Date(endOfMonth)
}
})
i was able to find all data entries on a specific month.
the data may look like something like this:
Date: dd/mm/yy Message:
1/5/2022 "Hello"
1/5/2022 "World"
1/5/2022 "!"
5/5/2022 "Hello World!"
8/5/2022 "Hello World!"
the desired answer would be 3 unique days in may.
How do i achieve this using mongodb? the simplest answer that come to mind is to use additional queries to group by unique days, but i have no idea how to do that using mongo provided i need to access the date.

This might solves your problem. it will return distinct messages.
Model.aggregate(
[
{ "$match": {
"date": {
"$gte": new Date(startOfMonth), "$lt": new Date(endOfMonth)
}
}},
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"day": { "$dayOfMonth": "$date" }
}
"count": { "$sum": 1 }
}}
],
function(err,result) {
// do something with result
}
);

You can use distinct
db.collection.distinct({date:{$gte:new Date(startOfMonth),$lt:new Date(endOfMonth)}}).length
if you are directly storing the date of it.
Note : This may not work if you're storing complete timestamp instead of date.

Related

Postman/JavaScript/API: Check if string contains dates and convert into time stamp

I am completely new to the topic of APIs and Postman and have the following question:
How can I detect multiple dates in a string and reformat them into a timestamp?
I pulled a JSON format via an API, then converted it to a string via the JSON.stringify function, and then stored it in an environment variable.
It now looks something like this:
[{“date”:“2000-01-01”,“value”:11.8432},{“date”:“2001-01-01”,“value”:112.2348},{“date”:“2002-01-01”,“value”:182.3777},{“date”:“2003-01-01”,“value”:15.0186},{“date”:“2004-01-01”,“value”:131.3781},{“date”:“2005-01-01”,“value”:145.3683}]
Now I’m trying to get this string back into a JSON format but I’d like to add a UNIX time stamp to the date (in milliseconds since January 1, 1970).
So it should look something like this:
[{“date”:946684800000,“value”:11.8432},{“date”:978307200000,“value”:112.2348},{“date”:1009843200000,“value”:182.3777}…
Does anyone know how to solve this within Postman (JavaScript for Postman)?
use moment library and the valueOf() method:
moment = require('moment')
let date = [{ "date": "2000-01-01", "value": 11.8432 }, { "date": "2001-01-01", "value": 112.2348 }, { "date": "2002-01-01", "value": 182.3777 }, { "date": "2003-01-01", "value": 15.0186 }, { "date": "2004-01-01", "value": 131.3781 }, { "date": "2005-01-01", "value": 145.3683 }]
date = date.map((item) => {
item.date = moment(item.date, "YYYY-MM-DD").valueOf()
return item
});
console.log(date)

Subtract days from a timestamp doesn't work with MongoDB

I still can't seem to do what I want to do. My Data Base:
{lastSeen: { $date: {$numberLong: 1614618000000 }}}
I want substract days to value and selects the documents where the value of the field is greater than or equal. I test this:
{"lastSeen": { "$gte": {"$date": { "$subtract": [ "$date", 1616000000000 ] }}}}
but the response is 'no result to show' on Gamesparks.
When i test with this query:
{"lastSeen": { "$gte": {"$date": "2021-03-13T00:00:00.000Z"}}}
i have responses.
An idea ? Thank you.

Count the number of events attended for a specific user in Cloudant using mapreduce

I'm using Cloudant's map reduce functionality and I want to find how many events (count of events object) the specific user with name (input from user) has attended for a date range (input from user).
I have docs that look like below.
{
user: {
name: 'peter pan'
},
startEventDateTime: <timestamp>,
endDateDateTime: <timestamp>,
events: [
{
name: 'La la land',
text: 'more info'
},
{
name: 'La la land',
text: 'more info'
}
]
}
Above means, user attended 2 events between between that start and end time. There are many documents for the same user for a different date range too with the events attended list.
How can I achieve this in Cloudant map reduce?
My Attempt:
unable to get map correctly. I can filter by name by doing
map:
function (doc) {
emit([doc.user, doc.events, startEventDateTime, endDateDateTime], doc)
}
reduce:
function (keys, values, rereduce) {
if (rereduce) {
return sum(values);
} else {
return values.length;
}
}
I would suggest considering a different format for your documents. Instead of having a user document with a list of events, make a separate document for each event, timestamped for the time at which it happened, such as:
{
"_id": "c48ee0881ce7c5d39243d2243d2e63cb",
"_rev": "1-c2f71fba5f09b129f1db20785f2429b2",
"user": "bob",
"datetime": "Thu 30 Nov 2017 09:46:02 GMT",
"event": {
"name": "lalaland",
"text": "more info"
}
}
Then you can rely on MapReduce to pick out date ranges per user. Here's a map function that does just that:
function (doc) {
if (doc && doc.user && doc.datetime) {
var when = new Date(Date.parse(doc.datetime));
emit([doc.user, when.getFullYear(), when.getMonth(), when.getDay()], 1);
}
}
and using the built-in reduce _sum. You can now use key ranges to slice the data. Say you want the events attended by user bob in Aug, 2017:
curl 'https://ACCT.cloudant.com/DBNAME/_design/DDOC/_view/VIEWNAME?startkey=\["bob", 2017, 7\]&endkey=\["bob", 2017, 8]&group=true&inclusive_end=false&reduce=true'
{
"rows": [
{
"key": [
"bob",
2017,
7,
4
],
"value": 1
}
]
}

Find object in array, to return the objects data

I have entries into the mongo database that hold daily entries and im trying to find a specific entry within an array. For example trying to find the coca cola for this user on the date using mongoose.
"_id": ObjectId("ID"),
"user_id": ObjectId("ID"),
"date": today,
"snacks":
[
{
"nutrients": [{...}],
"servings": 1,
"name": "Coca-Cola"
}
]
user_food.find({user_id : req.session.user_id, date: today}, {snacks:{[name:{"Coca-Cola"}]}}
I can query and retrieve the full entry by date with the following query:
user_food.findOne({user_id : req.session.user_id, date: today}, function (err, diary) {...});
My only problem is obtaining only the specific entry object by the name: snack - name.
You could change your query to look like this:
user_food.find({user_id : req.session.user_id, date: today, 'snacks.name': 'Coca-Cola' })
This will only find documents that have a snack name of "Coca-Cola" you can then project it if you wish to only send back relevant information

MongoDB Get Document Age in Hours

I am wondering if there is a way to get a MongoDB document age in hours? Here's what I have so far, but obviously I'm using a date object, it is not calculating the hours, and it's not giving the age, just the date it was created, so it is not giving the desired result. In fact, the $divide pipeline does not even allow for date objects. Any help is appreciated. Just as an FYI, the $views variable is a NumberInt32 type and the $created_at variable is a timestamp, like: 2014-05-20T00:01:08.629Z.
db.projects.aggregate({
$project: {
"result": {
$divide: ['$views', '$created_at']
}
}
)
If you're wondering, this code is to help sort popular posts, but of course, it's only part of it. Thanks for any help!
Presuming that $views and $created_at are fields in your document containing a number of views and the created timestamp as follows:
{
"_id" : ObjectId("537abe5e8da9877dbb0ef604"),
"views" : 5,
"created_at" : ISODate("2014-05-20T00:00:00Z")
}
Then just a little date math getting the difference from the current time should do:
db.projects.aggregate([
{ "$project": {
"score": { "$divide": [
{ "$divide": [
{ "$subtract": [
new Date(),
"$created_at"
]},
100*60*60
]},
"$views"
]},
"created_at": 1,
"views": 1
}}
])
So you are basically getting the difference in hours from the current time as a date object and the created_at value. Dividing that by a standard number for hours in a day, then dividing by your views in order to get your "score" result for sorting.
When you do math operations with two date objects then the result is returned as a number. So further operations with just numbers will work from then on.

Categories

Resources