Reputation: 796
I've been using mongodb 2.4.3 for a social networking application which returns profiles based on distance to the caller. I used the $nearSphere operator as follows:
db.profiles.find({loc: {$nearSphere: <lon, lat>}} ...).skip(0).limit(100);
I know that the $nearSphere operator only returns 100 results, however it does sort the result set by distance which is what I need, and since my application pages results in multiples of 100 anyway, I was able to iterate through the profiles list by distance just by incrementing the skip value as follows:
db.profiles.find({loc: {$nearSphere: <lon, lat>}} ...).skip(100).limit(100);
db.profiles.find({loc: {$nearSphere: <lon, lat>}} ...).skip(200).limit(100);
db.profiles.find({loc: {$nearSphere: <lon, lat>}} ...).skip(300).limit(100);
This has been working great for about a year. I recently upgraded to 2.6.1, and noticed that now, no matter what skip value I pass it, only the first 100 results are returned. I've since had to downgrade back to v2.4.3 in order to get this functionality back.
My question is, is this behavior a bug in 2.4.3, or a bug in 2.6.1? The docs don't mention this change as far as I can tell. If a bug in 2.4.3 that I happened to be taking advantage of, what's the best way to adapt while keeping the same functionality? Thanks!
Upvotes: 1
Views: 288
Reputation: 1542
the 100 limit you state is only for the '2d' index, so I guess you're using the '2d' index. from what I tested in version 2.6.3 (and 2.6.0, before I updated to the latest) it seems like there is a bug where the limit of this specific query doesn't take into account the the skip, so if you skip by 100 you should limit by 100 + limit
.
to reproduce (in mongo client):
db.test.drop();
db.test.ensureIndex({point: "2d"});
for (var i = 0; i < 200; ++i) {
db.test.insert({point:[1,2]});
}
db.test.insert({point:[1,2.01]});
db.test.find({point: {$nearSphere: [1,2]}}).skip(200).limit(201);
returns:
{ "_id" : ObjectId("53a476c6c83c83ebdd121038"), "point" : [ 1, 2.01 ] }
when you
db.test.find({point: {$nearSphere: [1,2]}}).skip(200).limit(1);
there's nothing.
for comparison, when you
db.test.find({}).skip(200).limit(1)
it returns
{ "_id" : ObjectId("53a476c6c83c83ebdd121038"), "point" : [ 1, 2.01 ] }
for '2dsphere' it works as you would expect.
Upvotes: 3