2016-02-09 56 views
1

我有一個流星應用程序,我試圖找到附近的人登錄到我的應用程序。我使用mdg:geolocation獲取座標,並將它們存儲在mongo中作爲geoJSON。由於Geolocation.latLng()被動,我必須等到它迴應之後才能向附近的人詢問mongo。我正在使用Tracker.autorun()並使用地理位置過濾器發佈集合。MeteorJS,mdg:geolocation和mongodb 2dsphere查詢

在客戶端:

Meteor.startup(function() { 
    Tracker.autorun(function() { 
    var coords = Geolocation.latLng(); 
    if (coords) { 
     Meteor.subscribe("people", coords); 
    } 
    }); 
}); 

在服務器:

Meteor.publish("games", function (c) { 
    return People.find({ location: 
         {$near: 
         {$geometry: 
          {type: "Point", coordinates: [c.lng, c.lat] } 
         , $maxDistance: 30} 
         } 
        }); 
}); 

雖然這是工作,但效率不高。每當瀏覽器位置發生變化時,都會導致新的訂閱。

我覺得必須有更好的方法來做到這一點。我對流星相當陌生,所以任何幫助表示讚賞。

回答

0

如果我告訴過你可以使用Mongo聚合,該怎麼辦?這裏的一般想法是,您希望「最近的地點」通過'People'集合中的更改自動進行更新,從而使用出版物和觀察。最好的

這是設置。第一步是獲取爲您包裝一些Mongo方法的聚合框架包。只需meteor add meteorhacks:aggregate,你應該做生意。這將爲您的集合添加一個聚合方法。

添加聚合框架支持的替代方法是直接調用您的mongoDB並訪問底層的集合方法,在這種情況下您需要.aggregate()方法。因此,使用它在mongoDB中連接:

var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db, 
    People = db.collection("People"); 

現在,您可以深入聚合框架並構建流水線查詢。

以下示例演示如何使用ES6 in Meteor觀察發佈中的聚合反應,與流星文檔中的'counts-by-room'example完全相同。

通過觀察,您將知道是否添加,更改或刪除了新位置。爲了簡單起見,重新運行每次(除了刪除)的聚合以及如果所述位置先前發表然後update發佈,如果除去位置然後remove位置從所述公佈,然後一個新的位置使用added event:

Meteor.publish('games', function(c) { 
    let initializing = 1, run = (action) => { 
     // Define our aggregation pipeline (aggregate(pipeline)) 
     let pipeline = [ 
      { 
       "$geoNear": { 
        "near": { "type": 'Point', "coordinates": [Number(c.lng), Number(c.lat)]}, 
        "distanceField": 'distance', 
        "maxDistance": 30, 
        "spherical": true, 
        "sort": -1 
       } 
      } 
     ] 
     People.aggregate(pipeline).forEach((location) => { 
      // Add each of the results to the subscription. 
      this[action]('nearest-locations', location._id, location) 
      this.ready() 
     }) 
    } 

    // Run the aggregation initially to add some data to your aggregation collection 
    run('added') 

    // Track any changes on the collection you are going to use for aggregation 
    let handle = People.find({}).observeChanges({ 
     added(id) { 
      // observeChanges only returns after the initial `added` callbacks 
      // have run. Until then, you don't want to send a lot of 
      // `self.changed()` messages - hence tracking the 
      // `initializing` state. 
      if (initializing && initializing--) 
      run('changed') 
     }, 
     removed(id) { 
      run('changed') 
     }, 
     changed(id) { 
      run('changed') 
     }, 
     error(err) { 
      throw new Meteor.Error("Aaaaaaaaah! Grats! You broke it!", err.message) 
     } 
    }) 

    // Stop observing the cursor when client unsubs. 
    // Stopping a subscription automatically takes 
    // care of sending the client any removed messages. 
    this.onStop(function() { 
     handle.stop(); 
    }) 
})