Mongo Geospatial query not filtering using $near and $MaxDistance


#1

I am trying to create an app that will limit places by a lat long in meteor. For some reason when I run the subscription I always get all the data return regardless of the $maxDistance I have set.

Here is some sample code of what I am doing:

test.coffee:

@Places = new Mongo.Collection 'Places'

if Meteor.isClient

   Meteor.subscribe('Places', {lat: 47.5105794, lng: -122.19099059999999})
   Template.closePlaces.helpers
     closePlaceData: () -> Places.find().fetch()


if Meteor.isServer
  Places.find().count() is 0
    Places.insert
      type: 'beauty'
      name: 'Salona Del Rey'
      address: '1234 Fake Street, Seattle, WA 98001'
      loc: {
        type: "Point"
        coordinates: [-122.2222,47.4700]
      }
      phone: '206-555-1212'
      operates: [{day:"Monday", start:"8", close:"22"},{day:"Tuesday", start:"8", close:"22"},{day:"Wednesday", start:"8", close:"22"},{day:"Thursday", start:"8", close:"22"},{day:"Friday", start:"8", close:"22"},{day:"Saturday", start:"10", close:"20"},{day:"Sunday", start:"12", close:"16"}]
      offers: ['0001', '0002', '0003', '0005']  `

Places._ensureIndex({'loc ':'2dsphere'})
Meteor.publish 'Places', (latLng) ->
  statement = {loc: {$near: { $geometry: { type: "Point", coordinates: [ latLng.lng , latLng.lat ]},$maxDistance: 10 }}}
  Places.find(statement)

test.html

<body>
     {{> closePlaces}}
 </body>
 <template name='closePlaces'>
   <ul class='places-list'>
   {{#each closePlaceData}}
     {{> closePlace}}
   {{/each}}
       </ul>
 </template>
 <template name='closePlace'>
     <div>{{ name }} <div class='button place'>More info &gt;</div></div>
 </template>

This subscription should only return something if the MaxDistance is set to 10,000. The way it is set right here (to 10) should not return anything.
Been banging my head against this one for a while and any help would be appreciated! Thanks.


#3

I use the following to achieve this (I transform the the lat/lan to Radians). Coords is something like

{
 latitude: 37.509554495623306,
 longitude: -122.29621011699783
}

for example what this yields

 navigator.geolocation.getCurrentPosition(function(coords){
  console.log(coords)
 })

this is my publish function

D2R = function(deg) {
	return deg * Math.PI / 180;
};
R2D = function(rad) {
	return rad / Math.PI * 180;
};
Meteor.publish('collection', function(coords, distance){
 geoquery = {$near: { 
  $geometry: {
   type: "Point" ,
    coordinates: [ D2R(coords.longitude) , D2R(coords.latitude) ]
   },
   $maxDistance: parseInt(distance)/100,
   $minDistance: 1
 }};
 return Collection.find(geoquey);
});

#4

What does you data look like for this? Does this work for you? It looks like you are doing the same thing as I am just you are converting to radians and passing in the distance as a var.

What does you client side code look like to render what you get back from the collection?

When I run the same query in the mongo database i get the appropriate returns (zero for distance of 10 and 1 for distance of 10000:

meteor:PRIMARY> db.places.find({loc:{$near:{$geometry: { type: “Point”, coordinates: [-122.1439848,47.4973886]}, $maxDistance : 10}}})
meteor:PRIMARY> db.places.find({loc:{$near:{$geometry: { type: “Point”, coordinates: [-122.1439848,47.4973886]}, $maxDistance : 10000}}})
{ “_id” : “snPQ4Fzu4c77Abk3W”, “type” : “beauty”, “name” : “Salona Del Rey”, “address” : “1234 Fake Street, Seattle, WA 98001”, “loc” : { “type” : “Point”, “coordinates” : [ -122.2222, 47.47 ] }, “phone” : “206-555-1212”, “operates” : [ { “day” : “Monday”, “start” : “8”, “close” : “22” }, { “day” : “Tuesday”, “start” : “8”, “close” : “22” }, { “day” : “Wednesday”, “start” : “8”, “close” : “22” }, { “day” : “Thursday”, “start” : “8”, “close” : “22” }, { “day” : “Friday”, “start” : “8”, “close” : “22” }, { “day” : “Saturday”, “start” : “10”, “close” : “20” }, { “day” : “Sunday”, “start” : “12”, “close” : “16” } ], “offers” : [ “0001”, “0002”, “0003”, “0005” ] }
meteor:PRIMARY>


#5

Yes, I am using radians and the distance is in meters. Check out the MongoDB GeoSpacial Index Tutorials.

http://blaze-maps.meteor.com uses all of this. The points are stored like this

{
 _id: "BwLmLtJxThxCxud3w", 
 title: "Hello World 12", 
 location: {
  type: "Point", 
  coordinates: [-2.136664836826825, 0.659349438145317]
 }
}

#6

what about autopublish, did you remove it? :smiley:


#7

Yes. Please note that minimongo (on the client) does not support geospacial queries. You must use pub/sub to get what you want. I guess I forgot to mention that :wink:


#8

I do have autopublish removed and I am running this on the client. Its kinda weird to me that it always returning all places. I would think if it wasnt working it would return no places all the time.

Jamgold i see in your find query you do not have a top level operator (i.e. geoquery = {$near: { )

Where as I am trying to specify which object to run the near on (i.e. {loc: {$near: {)

Is this the way I should do it? I have not been able to get the syntax correct for the case where I am not using the top level operator.


#9

Thanks Jamgold this helped. But, for some reason in one of the projects I am working in its not working appropriately. I created a new one and its working fine with the help you provided. Thanks!