Schema design for accumulated data on mongodb - mongodb

I'm searching and studing a lot how can i do this... I read many similar use cases, but i need some more complicated.
I will need collect this informations:
** Report Between April 2013 and Sept 2013 **
1- Monthly not accumulated report:
group1: {
"04" : {"photos" : 1, "documents" : 2, "likes" : 0},
...
"09" : {"photos" : 0, "documents" : 3, "likes" : 10} }, group2: ...
My group1 had 1 photo, 2 documents and 0 likes this mounth(4).
My group2 ...
2- Monthly accumulated report:
group1: {
"04" : {"photos" : 10, "documents" : 20, "likes" : 500},
...
"09" : {"photos" : 100, "documents" : 200, "likes" : 3000}
},
group2: ...
My group1 has at total 10 photos, 20 documents and 500 likes since the group was created until end range of date search.
And i will have the daily not accumulated report and daily accumulated report too.
The accumulated reports is how much photos, documents and likes my group had this month/day, like a historical report.
The not accumulated reports is how much photos, documents and likes my group got only this month/day.
The many use cases that i saw, it's about page views, analytics like google... but anyone has the accumulated data...
Anyone know a better schema design for my situation?
Thanks,
Diego

I got!
I created 3 colletions:
accumulated_stats: :_id, :photos, :documents
monthly_stats: :_id, date, :counts {:photos, :documents}, accumulated {:photos, :documents}
daily_stats: :_id, date, :counts {:photos, :documents}, accumulated {:photos, :documents}
Now, for each action, i will increment accumulated_stats, get the results and increment daily and monthly stats. it works as well!
But for showing the data.. i won't have all date time.. for instance:
2013-09-10
2013-09-11 ( do not have )
2013-09-12
2013-09-13
I'm looking for a way to construct the perfect date range. For instance, i don't have the day 11 on my collection, how can i bring it with the last existent values? any ideas?
Thanks,
Diego

Related

i am not getting data till today date in mongodb using $gte

what i want is to get the users who have created there account in between the range of dates and also want to get the customer with order count greater then 1 for those new customers, so what i am doing is trying to get the data greater then the last month i.e 1st of march 2020 but the output is giving me users till 1 april, why not till today i.e 11 april, the data is in following format
"_id" : ObjectId("1dv47sd1a10048521sa1234d"),
"updatedAt" : ISODate("2020-04-01T16:19:26.460+05:30"),
"createdAt" : ISODate("2020-04-01T16:18:46.066+05:30"),
"email" : "edx#gmail.com",
"phone" : "xxxxxxxxxx",
"password" : "$awdad$2b$10$4YaO6AEZqXA9ba0iz14ALi",
"dob" : "00/20/1990",
"stripeID" : "xxxxxxxxxxxxxxxx",
"__t" : "Customer",
"banned" : false,
"picture" : "link to image",
"name" : {
"first" : "ababab",
"last" : "Saaa"
},
"orderCount" : 2,
"creditCards" : [ ],
"addresses" : [ ],
"__v" : 0,
"isEmailVerified" : true
i have written a query for extracting data from the date greater then last month but it is giving me data till the 1 of april, my query is as follows
db.users.find({
"createdAt" : { "$gte" :new Date("2020-03-1") }
})
so i want to get data timm today from 1 march 2020 also order count is greter then 1,thanks in advance i am preety new with mongo
MongoDB only stores absolute times (aka timestamps or datetimes), not dates. As such the queries should generally be specified using times, not dates, also.
Furthermore, MongoDB always stores times in UTC. Different systems can operate in different timezones. For example, the shell may be operating in a different timezone from your application.
To query using dates:
Determine what timezone the dates are in.
Convert dates to times in that timezone. For example, 2020-03-01 00:00:00 UTC - 2020-03-31 23:59:59 UTC and 2020-03-01 00:00:00 -0400 - 2020-03-31 23:59:59 -0400 are both "March" and would match different sets of documents.
Convert the times to UTC. This may be something that a framework or library you are using handles for you, for example Mongoid in Ruby does this.
Use the UTC times to construct MongoDB queries.
This is stated in the documentation here.

Fetch documents from a MongoDB collection based on timestamp

I have a MongoDB collection with documents that look like this
{
"_id" : ObjectId("5aab91b2caa256021558f3d2"),
"Timestamp" : "2017-11-16T14:43:07.5357785+01:00",
"status" : 1,
"created_at" : 1521193394,
"updated_at" : 1521193394,
"deleted_at" : ""
}
Data gets entered into the collection every 15 minutes. Using the created_at field, which is in epoch time, I would like to find a way to fetch data at the top of every hour. So for example, data is entered at 12.00 12.15 12.30 12.45 13.00 13.15 13.30 13.45 14.00.
I would like to fetch entries from the collection that were entered at 12.00 13.00 and 14.00.
I am also open to suggestions as to whether or not using epoch time is the best way to go about it.
Using epoch time is really a good way to go.
Since you are stoing in seconds, every round hour can be divisible by 3600(seconds in hours) without remainder. You can make use of this property to find your documents.
db.collection.find({created_at: {$mod: [ 3600, 0 ]}});
According to $mod documentation, it will,
Select documents where the value of a field divided by a divisor has
the specified remainder
We provided divisor as 3600 and remainder as 0. This should give what you expect.
To ignore seconds:
For this condition, mod(epoch, 3600) should be less than 59. This query can be formed using $expr of mongo 3.6
db.collection.find({$expr: {$lte: [{ $mod: [ '$created_at', 3600 ] }, 59]}});
Hope this helps!

MongoDB squema design for objects with several dates

I'm building an event website. There are 2 types of events:
Events with specific dates and times. For example, a theatre show can have a show Jan 10 at 8pm, Jan 11 at 8pm and Jan 13 at 7pm.
Events which open a range of hours during several days. For example, an exhibition on a museum can open from Jan 10 to Jan 30 from 10am to 6pm.
I need to save the dates and times so that I can answer the following questions/queries:
Which events are going to happen tomorrow from 7pm to 12am?
Which events are going to happen this weekend?
Which events are about to finish? (the last day is less than one week away)
If we didn't have events type 2, we could have the following squema:
name
category
dates: an array of dates (each day would be on the array)
But because we have events type 2, it has to be different. I thought on having:
name
category
dates: an array of objects like {"2015-01-10 09:00": "2015-01-10 18:00"} with the range of hours of each day.
But I think it's not possible to do a query to solve Question 1 with this squema. Am I wrong?
How would you structure the data so I could answer those three questions?
thanks!
It was easier than I tought.
First, on MongoDB you can't have dates as keys.
The model is:
{
"name" : "Bob Dylan",
"category" : "Exhibition",
"dates" : [
{
"init" : ISODate("2015-01-08T08:00:00Z"),
"end" : ISODate("2015-01-08T19:00:00Z")
},
{
"init" : ISODate("2015-01-09T08:00:00Z"),
"end" : ISODate("2015-01-09T21:00:00Z")
},
{
"init" : ISODate("2015-01-10T08:00:00Z"),
"end" : ISODate("2015-01-10T21:00:00Z")
}
],
"createdAt" : ISODate("2015-01-09T16:33:51.338Z")
}
And the query is:
return Events.find({
'dates.init' : { $gte: dateInit },
'dates.end' : { $lte: dateEndPlusOneDay }
});

Aggregation framework for MongoDB

I have following schema:
Customer ID
Location Name
Time of Visit
The above stores the information of all customer's visit at various locations.
I would like to know if there's a way to write an aggregate query in MongoDB, so that it gives the Total Visitor information by different sections of the day, per day per location.
Sections of the day:
EDIT:
12 am - 8 am
8 am - 11 am
11 am - 1 pm
1 pm - 4 pm
4 pm - 8 pm
8 pm - 12 pm
If a customer visits a location on the same day and same section of the day more than once, it should be counted just once. However, if that customer visits a location on the same day but for different sections of the day, it should be counted exactly once for each of the section of the day he has appeared in.
Example:
Customer 1 visits store A on day 1 at 9:30 AM
Customer 1 visits store A on day 1 at 10:30 PM
Customer 1 visits store B on day 2 at 9:30 AM
Customer 1 visits store B on day 2 at 11:30 AM
Customer 1 visits store B on day 2 at 2:45 PM
Customer 2 visits store A on day 1 at 9:45 AM
Customer 2 visits store B on day 1 at 11:00 AM
Customer 2 visits store B on day 2 at 9:45 AM
Final output of repeat visits:
Store B, Day 1, Section (00:00 - 08:00) : 0 Visitors
Store B, Day 1, Section (08:00 - 16:00) : 2 Visitors
Store B, Day 1, Section (16:00 - 24:00) : 1 Visitors
Store B, Day 2, Section (00:00 - 08:00) : 0 Visitors
Store B, Day 2, Section (08:00 - 16:00) : 2 Visitors
Store B, Day 2, Section (16:00 - 24:00) : 0 Visitors
Is there any way the above kind of query could be done using aggregation framework for MongoDB?
Yes, this can be done quite simply. It's very similar to the query that I describe in the answer to your previous question, but rather than aggregating by day, you need to aggregate by day-hour-combinations.
To start with, rather than doing a group you will need to project a new part of date where you need to transform your "Time of Visit" field to the appropriate hour form. Let's look at one way to do it:
{$project : { newDate: {
y:{$year:"$tov"}, m:{$month:"$tov"}, d:{$dayOfMonth:"$tov"},
h: { $subtract :
[ { $hour : "$tov" },
{ $mod : [ { $hour : "$tov" }, 8 ] }
]
}
},
customerId:1, locationId:1
}
}
As you can see this generates year, month, day and hour but the hour is truncated to mod 8 (so you get 0, 8(am), or 16 aka 4pm.
Next we can do the same steps we did before, but now we are aggregating to a different level of time granularity.
There are other ways of achieving the same thing, you can see some examples of date manipulation on my blog.

MongoDB Aggregation Framework Date NOW

I am attempting to perform a calculation in an aggregation based on the day of the current month. For example, I want to divide the total number of transactions by the day of the month to get transactions per day.
The problem is I can't figure out how to get the current date. I see plenty of examples where it's hardcoded, but what I need is more like the MySQL NOW() function.
I've tried something like this:
> db.statistics.aggregate([{$project: {dayofmonth: {$dayOfMonth: Date()}}}])
{
"errmsg" : "exception: can't convert from BSON type String to Date",
"code" : 16006,
"ok" : 0
}
But that produces the error you see.
How can I get the current day of the current month for use in an aggregation calculation?
You almost did it. You have to write new Date()
db.statistics.aggregate([
{$project: {dayofmonth: {$dayOfMonth: new Date()}}}
])
it will produce results like this:
{
"result" : [
{
"_id" : "statisctiId",
"dayofmonth" : 9
}
}