MongoDB 1.7: Get results within a radius using the spherical model

442 views
Skip to first unread message

Moe Loepi

unread,
Sep 23, 2010, 3:40:54 PM9/23/10
to mongodb-user
Hello Everyone,

I am currently working on a mongo database which contains a lot of
geodata. I want to query the objects within a certain range given in
kilometres.

As the distance model of the current production release is rathing
confusing, I was happy to see that Mongo 1.7 introduced a new
spherical model which should make it easier to perform this task.

To illustrate the problem, I created a sample dataset of geodata:

db.sights.insert({ name : 'Trafalgar Square' , city : 'London', loc :
[-0.1275,51.507778] });
db.sights.insert({ name : 'Piccadilly Circus' , city : 'London', loc :
[-0.134529,51.509861] });
db.sights.insert({ name : 'London Bridge' , city : 'London', loc :
[-0.087778,51.508056] });
db.sights.insert({ name : 'Hyde Park' , city : 'London', loc :
[-0.169644,51.507327] });
db.sights.insert({ name : 'Eiffel Tower' , city : 'Paris', loc :
[2.2945,48.8583] });
db.sights.insert({ name : 'Van Gogh Museum' , city : 'Amsterdam',
loc : [4.881053,52.358236] });
db.sights.insert({ name : 'Brandenburg Gate' , city : 'Berlin', loc :
[13.377722,52.516272] });
db.sights.insert({ name : 'Stonehenge' , city : 'Amesbury', loc :
[-1.826389,51.178889] });

db.sights.ensureIndex( { loc : "2d" } )

Starting from Trafalgar Square these are the distances according to
Google Maps:

Trafalgar Square: 0 km
Piccadilly Circus: 0.54 km
London Bridge: 2.76 km
Hyde Park: 2.92 km
Eiffel Tower: 341.3 km
Van Gogh Museum: 356.77 km
Brandenburg Gate: 931.52 km
Stonehenge: 123.76 km

First I wanted to see, how accurate MongoDB's spherical distance model
is (second column: distance, third column: distance * 6371 to get km)

db.runCommand( { geoNear : "sights", near: [ -0.1275, 51.507778 ],
spherical : true } )

Piccadilly Circus 0,000084633 0.54
London Bridge 0,000431487 2.75
Hyde Park 0.00457871 2.92
Eiffel Tower 0.053574796 341.33
Van Gogh Museum 0.055892458 356.1
Brandenburg Gate 0.145924356 929.68
Stonehenge 0.019390261 123.54

Wow! That works pretty well.

After that I wanted to write a query which returns all objects within
a certain range. My first approach was:

db.sights.find({"loc" : {"$within" : {"$centerSphere" :
[[-0.1275,51.507778], 1]}}});

This gives me following error: "Spherical distance would require
wrapping, which isn't implemented yet" (Code: 13462)

Ok, well, it's a development release. So I tried using the geoNear
command setting a maxDistance

db.runCommand( { geoNear : "sights", near: [ -0.1275, 51.507778 ],
maxDistance : 0.02, spherical : true } )

For some reason this only returns four objects:

Trafalgar Square, Piccadilly Cirucs, London Bridge, Hyde Park.

According to the geoNear command without maxDistance Stonehenge has a
distance of 0.019, so shouldn't it be included within this query?

Using trial and error I found out, that a maxDistance of
0.000953617217 returns 4 objects within London while 0.000953617216
returns only one. This number doesn't seem to correlate with the
distance number, so I'm not quite sure, what it does.

This leads to following questions:
- Is this a bug of the development release or did I miss something?
- Is there a (simple) approach to solve that task (query objects
within a certain range given in km)? Preferably something that can be
used on a production release of MongoDB and that performs well even
with millions of datasets.

Any hint would be appreciated.

Moe

Mathias Stearn

unread,
Sep 23, 2010, 4:25:30 PM9/23/10
to mongod...@googlegroups.com
$centerSphere is mostly intended for queries upto a few hundred miles or km. By querying for a radius of 1 you are asking for everthing within 6371km. Try again with a smaller radius.

It's possible that we need to add some fudge-factor to maxDistance since there are a few places where computational errors can creep in. MaxDistance is also less well tested since it isn't used in our randomized geo test suite. I'll see if I can find a way to work it in.

Could you provide the exact data you imported along with a the exact queries you ran? That will help reproducing your issues.

Thanks


--
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To post to this group, send email to mongod...@googlegroups.com.
To unsubscribe from this group, send email to mongodb-user...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mongodb-user?hl=en.


Moe Loepi

unread,
Sep 23, 2010, 4:47:20 PM9/23/10
to mongodb-user
On Sep 23, 10:25 pm, Mathias Stearn <math...@10gen.com> wrote:
> $centerSphere is mostly intended for queries upto a few hundred miles or km.
> By querying for a radius of 1 you are asking for everthing within 6371km.
> Try again with a smaller radius.

Mathias, you are right of course. I can't belive I spent so much time
on it. When I wrote this query I though I'll start with 1 just to see
what happens. But when I saw the error I thought this feature
generally is missing in this release and didn't try further. However,
if I use 0.0005 it works perfectly fine and gives me exact what I
want. Problem solved :)

Btw the spherical model is a great improvement to MongoDB and I can't
wait for the production release to be released. Good work.

Thanks for you help!

Moe
Reply all
Reply to author
Forward
0 new messages