我有一个流星应用程序,我试图找到附近的人登录到我的应用程序。我正在使用mdg:geolocation
来获取坐标并将它们存储在mongo中geoJSON
。由于Geolocation.latLng()
被动,我必须等到它响应之后我才能向附近的人查询mongo。我是通过使用Tracker.autorun()
并使用地理位置过滤器发布集合来实现的。
在客户端:
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 :(得分:0)
如果我告诉您可以使用Mongo聚合怎么办?这里的一般想法是,您需要最近的位置'通过'People'
集合中的更改自动更新,因此使用发布与观察。最好的
这是设置。第一步是获取聚合框架包,它包含一些Mongo方法。只需meteor add meteorhacks:aggregate
即可开展业务。这将为您的集合添加聚合方法。
添加聚合框架支持的另一种方法是直接调用mongoDB并访问底层集合方法,在这种情况下,您需要.aggregate()方法。因此,使用它来连接mongoDB:
var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db,
People = db.collection("People");
现在您可以深入了解聚合框架并构建管道查询。
以下示例演示如何使用ES6 in Meteor使用example获取发布中的聚合反应,与流星文档中的'counts-by-room'
update
完全相同。
通过观察,您将知道是否添加,更改或删除了新位置。为简单起见,每次重新运行聚合(删除除外),如果该位置先前已发布,则 remove
发布,如果该位置已删除,则 {{3} 来自发布的位置,然后针对新位置使用 added
事件:
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();
})
})