MongoDB row index limit query like SQL - mongodb

I would like to retrieve a list that contains an specified record under some conditions and only retrieve a number of records before and a number of records after that record. Are there any solutions?
For example, I have a MongoDB schema { id, date, section }
Data set:
100, 26 Aug 2014 11:00, A
110, 26 Aug 2014 11:01, A
140, 26 Aug 2014 12:00, A
141, 27 Aug 2014 12:00, B
200, 30 Aug 2014 11:00, A
210, 01 Sep 2014 11:01, B
290, 02 Sep 2014 12:00, A
300, 26 Sep 2014 12:00, A
301, 27 Oct 2014 12:00, B
302, 30 Oct 2014 11:23, A
410, 01 Oct 2014 15:01, B
590, 02 Oct 2014 12:00, A
600, 26 Nov 2014 00:00, A
I would like to get a list, which contains an unique id = 300 and 3 records before and 3 records after that record with id = 300, sorted by date under section A.
The output:
140, 26 Aug 2014 12:00, A
200, 30 Aug 2014 11:00, A
290, 02 Sep 2014 12:00, A
300, 26 Sep 2014 12:00, A <-- middle
302, 30 Oct 2014 11:23, A
590, 02 Oct 2014 12:00, A
600, 26 Nov 2014 00:00, A
I have a stupid approach:
get the date (let say it's 26 Sept 2014 12:00) of the specified id = 300 with section A
set a query to find records that the date is greater than and equal to 26 Sept 2014 12:00 ordered by date, limited by 3 records.
set a query to find records that the date is less than 26 Sept 2014 12:00 ordered by date, limited by 3 records.
combine two lists.
Is there any better approaches to just retrieve this kind of list in a query or in better performance? Thank you.

Let's your schema name be USER. You could use below mongo db query to fetch the result
$sort function :
1 represents ascending
-1 represents descending
Refer documentation : $Sort Documentation
Query will be :
db.user.aggregate({$match : { "id" : 300}},{$sort : {"date": 1 }},{$skip : 0},{$limit : 10});
$skip value will be your limit value after first query
db.user.aggregate({$match : { "id" : 300}},{$sort : {"date": 1 }},{$skip : 10},{$limit : 10});
Refer Documentation : Aggregation Documentation

$skip and $limit in aggregation framework
Here is a good example of using skip and limit which should help you achieve the SELECT TOP X or LIMIT X
Note: I'm assuming you want to use the aggregate framework based on the tagging of this question.
I believe this should do it
x = 300;
db.user.aggregate({$match : { "id" : {$lte: x+10,$gte: x-10 }},{$sort : {"date": 1 }}});

Related

Date minus date is not giving desired answer - IONIC 2

When I try to subtract
Wed Dec 06 2017 15:58:59 GMT+0530 (India Standard Time) minus Tue Nov 28 2017 00:00:00 GMT+0530 (India Standard Time) , the answer which is coming is -22
But the answer should be 6
What is going wrong and where, below is my page.ts code:
this.tt = new Date();
this.tt1 = this.datePipe.transform(this.tt,'dd/mm/yyyy');
console.log(this.ent[0],"server DATE");
// in console we see this - 28-NOV-17 server DATE
var firstDate= new Date(this.ent[0]); //Jan 01 2017 00:00:00
var secondDate = new Date();//Jan 04 2017 00:00:00
console.log(firstDate);
// answer in console - Tue Nov 28 2017 00:00:00 GMT+0530 (India Standard Time)
console.log(secondDate);
//answer in console - Wed Dec 06 2017 15:58:59 GMT+0530 (India Standard Time)
console.log(secondDate.getDate() - firstDate.getDate() );
//answer in console - -22
Date.getDate() gives the "dd" of the date (in your case 6 and 28 which explains the result being -22).
I'm a bit confused with the expected result being 6. So maybe my answer won't fit you. What I would do however is convert the date in time, do the substraction and convert it back to number of days.
So
Math.Floor((secondDate.getTime() - firstDate.getTime()) / 86400000);
(86400000 being 1000 (milliseconds) * 3600 (seconds in an hour) * 24 (number of hours in a day)
you can convert both dates to timestamp and subtract the timestamp you will get the result days in millis now convert it to days
getTimestamp(dateParam:string):string{
var date = new Date(dateParam); // some mock date
var milliseconds = date.getTime();
return milliseconds.toString();
}
var one_day=1000*60*60*24;
console.log(Math.ceil(getTimestamp(secondDate) - getTimestamp(firstDate))/(one_day) );

find results not matching date in selector

A Meteor client Template returns mongodb cursor. The collection has 3 documents which contain date field. I expected the find to return 3 documents, but it only gave one the date of which is Mon Aug 08 2016 00:00:00 GMT+1000 (AEST).
Why is that and how can I get the 3 documents? Thanks
"date" : ISODate("2016-08-08T14:00:00Z"),
"date" : ISODate("2016-08-08T14:00:00Z"),
"date" : ISODate("2016-08-07T14:00:00Z"),
console.log(start); //=> Sun Aug 07 2016 00:00:00 GMT+1000 (AEST)
console.log(end); //=> Mon Aug 08 2016 00:00:00 GMT+1000 (AEST)
console.log(myCol.find({date: {$gte: start, $lte: end}}).fetch()); // expected 3 not just 1
the code below shows how the date was before inserting in the collection.
const date = cheerioObj(this).next().html().trim();
const dArr = date.split('/');
const dObj = new Date(parseInt(dArr[2]), parseInt(dArr[1]) - 1, parseInt(dArr[0]));
EDIT: Sorry, it's late.
It may be to do with your .fetch() method. Try iterating the cursor instead:
var myArray = db.users.find({...}).toArray();
Then access each in a for loop.

Date range queries mongodb

I've two collections one is random and other one is 'msg'
In message I've a document like
{ "message": "sssss", postedAt: Fri Jul 17 2015 09:03:43 GMT+0530 (IST) }
For random collection, there is a script which generates random number every minute
like
{ "randomStr": "sss", postedAt: Fri Jul 17 2015 09:03:43 GMT+0530 (IST) }
{ "randomStr": "xxx", postedAt: Fri Jul 17 2015 09:04:43 GMT+0530 (IST) }
{ "randomStr": "yyy", postedAt: Fri Jul 17 2015 09:05:43 GMT+0530 (IST) }
Notice the change in timings, for every mintute there is a new record.
Now, my issue is
when I query for message collection, I'll get one record.
Lets's say this
{ "message": "sssss", postedAt: Fri Jul 17 2015 09:03:13 GMT+0530 (IST) }
now I want to get the record from random collection which posts at exact minute
this message is posted at 09:03, I want to get the record from random collection which postedat exactly same time 09:03.
How to do that? Any help appreciated. Thx.
Note: I'm doing this in meteor
Edit
Added image for first comment
So the point here is 'actually use a range' and also be aware of the Date value you get in return. So as a basic example in principle.
The time right now as I execute this is:
var date = new Date()
ISODate("2015-07-17T04:02:04.471Z")
So if you presume then that your actual timestamp in the document is "not exactly to the minute" (like above) nor is it likely the "random record" is so then the first thing to do is "round" it to the minute:
date = new Date(date.valueOf() - date.valueOf() % ( 1000 * 60 ))
ISODate("2015-07-17T04:02:00Z")
And of course the "end date" is just one minute after that:
var endDate = new Date(date.valueOf() + ( 1000 * 60 ))
ISODate("2015-07-17T04:03:00Z")
Then when you query "rqndom" you just get the "range", with $gte and $lt operators:
db.random.find({ "postedAt": { "$gte": date, "$lt": endDate } })
Which just retrieves your single "write once a minute" item from "random" at any possible value within that minute.
So basically:
Round your input retrieved date to the minute
Search on the "range" betweeen that value and the next minute

IndexedDB with range queries

I would like to find which date ranges overlaps another date range in IndexedDB.
Something like the following query:
SELECT * FROM events
WHERE (periodStart >= start AND periodStart < end)
OR (start >= periodStart AND start <= periodEnd)
Events looks like the following object:
[{
title: 'foo',
start: 'Tue Oct 29 2013 10:19:52 GMT-0400 (EDT)',
end: 'Tue Oct 29 2013 13:19:52 GMT-0400 (EDT)'
},
{
title: 'bar',
start: 'Tue Oct 30 2013 00:00:00 GMT-0400 (EDT)',
end: 'Tue Oct 31 2013 00:00:00 GMT-0400 (EDT)'
}]
To my knowledge, no ability to do unions in indexeddb (the OR).
So, as that kinda sucks, here is a half thought out solution that maybe puts you on the course: something like find the min of the set, and the max of the set, and then a query descending and a query ascending but just get the first record from each cursor, and then, something.

Date object in a MongoDB collection

In a collection in my MondoDB database i have a collection like follows:
{ "_id" : ObjectId("4d0d3945e69a56cf504375b7"), "action" : "Click", "dt" : "Sun Dec 19 2010 03:44:21 GMT+0000 (UTC)"}
dt is a Date object. If i do db.mycollection.find({action:"Click"})the record comes up. But db.mycollection.find({dt:'Sun Dec 19 2010 03:44:21 GMT+0000 (UTC)'})does not show any records, since i guess dt is a Date object.
How to query by dt in the above case ?
Please Help
Thank You
db.mycollection.find({dt:ISODate('Sun Dec 19 2010 03:44:21 GMT+0000 (UTC)')})