【问题标题】:MeteorJS, mdg:geolocation, and mongodb 2dsphere queriesMeteorJS、mdg:geolocation 和 mongodb 2dsphere 查询
【发布时间】:2016-02-09 11:56:35
【问题描述】:

我有一个流星应用程序,我试图找到附近登录我应用程序的人。我正在使用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}
                      }
                    });
});

虽然这有效,但效率不高。每次浏览器位置发生变化都会导致新的订阅。

我觉得必须有更好的方法来做到这一点。我对流星相当陌生,因此不胜感激。

【问题讨论】:

    标签: mongodb meteor geolocation


    【解决方案1】:

    如果我告诉你你可以使用 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 事件获取新位置:

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

    【讨论】:

      猜你喜欢
      • 2014-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-14
      • 2014-08-01
      • 2021-04-17
      相关资源
      最近更新 更多