Adam Berlinsky-Schine
Adam Berlinsky-Schine

Reputation: 682

Meteor JS $near Reactive Sorting

I was happy to see that $near support for geospatial indexes was recently added to minimongo in Meteor 0.6.6. However, it doesn't appear that the sorting behavior of $near (it should sort in order of distance) is reactive. That is, when an document is added to the collection, the client loads it, but always at the end of the result list, even if it is closer to the $near coordinate than other documents. When I refresh the page, the order is corrected.

For example:

Server:

Meteor.publish('events', function(currentLocation) {
    return Events.find({loc: {$near:{$geometry:{ type:"Point", coordinates:currentLocation}}, $maxDistance: 2000}});
});

Client:

Template.eventsList.helpers({
    events: function() {
        return Events.find({loc: {$near:{$geometry:{ type:"Point", coordinates:[-122.3943391, 37.7935434]}}, 
$maxDistance: 2000}});
    }
});

Is there a way to get it to sort reactively?

Upvotes: 3

Views: 1707

Answers (1)

imslavko
imslavko

Reputation: 6676

There is nothing special about sorting reactivity for $near queries as supposed to any other query in minimongo: minimongo uses some sorting function either based on your sort specifier passed in query or a default sorting for queries containing $near operator.

Minimongo would sort everything and compare previous order with the new order every time something updates.

From your original question, it's unclear what behavior you expect and what do you see instead. Just to prove mentioned sorting works reactively, I wrote a mini-app to show it:

html templates:

<body>
  {{> hello}}
</body>

<template name="hello">
  Something will go here:
  {{#each things}}
    <p>{{name}}
  {{/each}}
</template>

and JS file:

C = new Meteor.Collection('things');

if (Meteor.isClient) {
  Template.hello.things = function () {
    return C.find({location:{$near:{$geometry:{type: "Point",coordinates:[0, 0]}, $maxDistance:50000}}});
  };

}

if (Meteor.isServer) {
  Meteor.startup(function () {
    C.remove({});

    var j = 0;
    var x = [10, 2, 4, 3, 9, 1, 5, 4, 3, 1, 9, 11];

    // every 3 seconds insert a point at [i, i] for every i in x.
    var handle = Meteor.setInterval(function() {
      var i = x[j++];
      if (!i) {
        console.log('Done');
        clearInterval(handle);
        return;
      }

      C.insert({
        name: i.toString(),
        location: {
          type: "Point",
          coordinates: [i/1000, i/1000]
        }
      });
    }, 3000);
  });
}

What I see right after starting application and opening the browser: Numbers appear on the screen one by one from the x array. Every time new number arrives, it appears on the correct spot, keeping the sequence sorted all the time.

Did you mean something else by '$near reactive sorting'?

Upvotes: 7

Related Questions