【问题标题】:Returning the Results as well as subscribing in Meteor Mongo Geosearch返回结果以及订阅 Meteor Mongo Geosearch
【发布时间】:2015-10-27 20:29:26
【问题描述】:

使用 Meteor.js,我的 pub/sub 可以完美运行以下代码。我能够通过我的参数并毫无问题地返回游标。

我的目标是显示当前用户位置和数据库结果之间的距离。

由于 mongodb 已经计算了获得结果集的距离,我不想在其他地方再次计算它。我想返回 $geoNear 记录的here 的 geoNear.results[n].dis 结果,但无法找到一种实用的方法来解决它。我很欣赏发布仅将光标返回到文档,但想知道是否有某种方法可以以某种方式附加结果...

Meteor.publishComposite("public", function(location, distance) {
return {
find: function() {
      return Tutors.find({},
                  {
                    $geoNear: {
                        $geometry: {
                          type: "Point" ,
                          coordinates: [ location.lng , location.lat ]
                        },
                        $maxDistance: distance,
                      },
                    }
                  );
                }
}
});

我的订阅参数只是一个 lat/lng 对象和以米为单位的距离。

【问题讨论】:

    标签: mongodb meteor


    【解决方案1】:

    如果我告诉你可以使用 Mongo aggregation 会怎样?这里的总体思路是让当前用户位置和数据库结果之间的距离随着 'Tutors' 集合的变化而自动更新,因此使用 publication 和观察来实现此目的。

    这是设置。第一步是获取聚合框架包,它为您包装了一些 Mongo 方法。只需meteor add meteorhacks:aggregate,您就应该在家干爽。这将为您的集合添加一个 aggregate() 方法。

    添加聚合框架支持的另一种方法是直接调用您的 mongoDB 并访问底层集合方法,在这种情况下您需要 aggregate() 方法。所以,用它来连接 mongoDB :

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

    现在您可以深入了解聚合框架并构建管道查询。以下示例演示了如何在发布反应式中使用 observe 在发布中使用 ES6 in Meteor 获取聚合。这遵循流星文档中的'counts-by-room' example。通过 observe,您可以了解是否添加、更改或删除了新位置。为简单起见,每次重新运行聚合(删除除外),如果该位置先前已发布,则 update 发布,如果该位置已被删除,则 remove来自发布的位置,然后使用 added:

    Meteor.publish('findNearestTutors', function(opts) {
        let initializing = 1, run = (action) => {
            // Define the aggregation pipeline
            let pipeline = [
                {
                    $geoNear: {
                        near: {type: 'Point', coordinates: [Number(opts.lng), Number(opts.lat)]},
                        distanceField: 'distance',
                        maxDistance: opts.distance,
                        spherical: true,
                        sort: -1
                    }
                }
            ]
            Tutors.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 = Tutors.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("Houston, we've got a problem here!", 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();
        })
    })
    

    【讨论】:

    • 太棒了。你成功了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 2015-04-21
    • 2021-07-18
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多