MongoDB squema design for objects with several dates - mongodb

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 }
});

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.

Not getting accurate result in mongodb using gte and lte query

This is my user collection in mongodb
{
"_id" : NumberLong(104060),
"age" : 41,
"username" : "appubhai75#gmail.com",
"roles" : [
"ROLE_USER"
],
"firstName" : "Apurva",
"lastName" : "Shah",
"email" : "appubhai75#gmail.com",
"createdDate" : ISODate("2016-02-08T12:23:02.001Z"),
}
i am using criteria like this
criteria = new Criteria().orOperator(name, email)
.andOperator(genderCriteria).and("_id").ne(id).and("createdDate").gte(startDate).lte(endDate);
when i am passing startdate and enddate like:
Start date is::2015-12-16T00:00:00.000+05:30
end date is::2016-02-08T00:00:00.000+05:30
this user is not coming ,but when i change my enddate to
end date is::2016-02-09T00:00:00.000+05:30
then it is coming.
If i am using gte and lte then it must include the date equal to also .Like,when i pass the date from 16 dec to 8 feb, then it is giving all the users with created date 16 to 7 feb. not including the user with created date 8 feb,and when i am passing 16 dec to 9 feb then it include 8 feb user.Is anything am doing wrong i am confuse.Please help.
Thank you.
You won't get results for this
Start date is::2015-12-16T00:00:00.000+05:30
end date is::2016-02-08T00:00:00.000+05:30
Check the created Date for user it is ISODate("2016-02-08T12:23:02.001Z") date is equal but not the time.Overall your user date is not in your range .Mongo it checks for both date and time equality.
The one solution you can have is at your application side add additional time 24*60*60 - 1 to this Date createdDate using DateUtils in org.apache.commons.lang.time(Apache Commons Lang)
DateUtils.addSeconds(createdDate,24*60*60-1);
Important Assuming that you will send only date in request.You have to add above code to pre proprocess your request object but not when your inserting.When ever a request comes add this piece of code.It will work fine

mongodb indexable $and query possible?

I'm developing an app using a MongoDB database that needs to check for items enabled for today's particular weekday.
Items can be enabled for any individual days of the week. (eg: Monday and Wednesday, or Tuesday and Thursday and Saturday, every day, whatever)
I was going to do this:
var currentWeekDay = Math.pow(2,new Date().getDay());
Therefore
Sunday === 1
Monday === 2
Tuesday === 4
Wednesday === 8
...
Saturday === 64
An example item might be like this
{_id:'blah', weekDays:127}
Now I want to query all items that are enabled for today...
MongoDB has an operator $and, but that's only for logical operations.
It has $bitsAnySet, but it looks like it's only implemented in 3.16.
https://jira.mongodb.org/browse/SERVER-3518
I'm running MongoDB v2.6.10.
So I'm wondering how to come up with a sensible indexable query.
Maybe
{_id:'blah', w0:1, w1:1, w2:1, w3:1, w4:1, w5:1, w6:1} //every day
{_id:'blah', w0:1, w1:0, w2:0, w3:0, w4:0, w5:0, w6:1} //Sat and Sun
That would be easily indexable. Can anyone think of a more terse way of doing it?
One option would be storing days as an array of integers:
{ '_id' : '1' , 'weekDays' : [0,1,2,3,4] } // mon-fri
{ '_id' : '2' , 'weekDays' : [5,6] } // sat-sun
Then you could create a simple index on weekDays field:
db.collection.createIndex({ weekDays : 1 })
And querying would also be pretty simple:
db.collection.find({weekDays : 2}) // wed

Schema design for accumulated data on 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

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
}
}