MeteorJS、mdg:geolocation和mongodb 2dsphere查询

MeteorJS、mdg:geolocation和mongodb 2dsphere查询,mongodb,meteor,geolocation,Mongodb,Meteor,Geolocation,我有一个meteor应用程序,我试图找到附近的人登录到我的应用程序。我正在使用mdg:geolocation获取坐标,并将它们作为geoJSON存储在mongo中。由于Geolocation.latLng()是被动的,我必须等到它响应后才能查询mongo附近的人。我使用Tracker.autorun()并发布一个带有地理位置过滤器的集合 在客户端: Meteor.startup(function() { Tracker.autorun(function () { var coords

我有一个meteor应用程序,我试图找到附近的人登录到我的应用程序。我正在使用
mdg:geolocation
获取坐标,并将它们作为
geoJSON
存储在mongo中。由于
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}
                      }
                    });
});
虽然这是可行的,但效率不高。每次浏览器位置更改时,都会导致新订阅


我觉得必须有更好的方法来做到这一点。我是meteor的新手,非常感谢您的帮助。

如果我告诉您可以使用Mongo聚合怎么办?这里的总体思路是,您希望“最近的位置”随着
“人”
集合的更改而自动更新,因此使用带有观察的出版物。最好的

这是设置。第一步是获取聚合框架包,它为您封装了一些Mongo方法。只要
meteor添加meteorhacks:aggregate
,你就应该开始做生意了。这将向集合中添加聚合方法

添加聚合框架支持的另一种方法是直接调用mongoDB并访问底层集合方法,在本例中,您需要.aggregate()方法。因此,在mongoDB中使用此连接:

var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db,
    People = db.collection("People");
现在,您可以深入到聚合框架并构建管道查询

下面的示例演示了如何使用“观察”获取发布中的聚合,与meteor文档中的“按房间计数”中完全相同

通过观察,您将知道是否添加、更改或删除了新位置。为简单起见,每次重新运行聚合(删除除外),如果该位置以前已发布,则发布;如果该位置已删除,则从发布中删除该位置,然后对于新位置使用事件:

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();
    })
})

如果我告诉你可以使用Mongo聚合呢?这里的总体思路是,您希望“最近的位置”随着
“人”
集合的更改而自动更新,因此使用带有观察的出版物。最好的

这是设置。第一步是获取聚合框架包,它为您封装了一些Mongo方法。只要
meteor添加meteorhacks:aggregate
,你就应该开始做生意了。这将向集合中添加聚合方法

添加聚合框架支持的另一种方法是直接调用mongoDB并访问底层集合方法,在本例中,您需要.aggregate()方法。因此,在mongoDB中使用此连接:

var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db,
    People = db.collection("People");
现在,您可以深入到聚合框架并构建管道查询

下面的示例演示了如何使用“观察”获取发布中的聚合,与meteor文档中的“按房间计数”中完全相同

通过观察,您将知道是否添加、更改或删除了新位置。为简单起见,每次重新运行聚合(删除除外),如果该位置以前已发布,则发布;如果该位置已删除,则从发布中删除该位置,然后对于新位置使用事件:

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();
    })
})