如何将 "distance" 注入位置列表

How to inject "distance" into a list of Locations

我们有一个具有“Location”字段的模型事件。

我们想要实现的是:给定一个 lat/lon 坐标附近的查询,我们希望列表中的每个结果也有一个字段,称为 distance,即距结果集中每个对象的 location.geo 坐标。

我们在KeystoneJS Location类型定义中看到有underscore methods for this.

但我们无法弄清楚如何将其作为列表中每个结果的 "virtual" 注入。

有没有人知道如何将请求的 Lat/Lon 传递给那些下划线方法并将其填充到结果列表中?

var q = Event.paginate({ page: req.query.page || 1, perPage: req.query.max || 20 })
                         .where('eventDate').gt(since)
                         .where('state').equals('published')
                         .sort("eventDate")

if (req.query.lon && req.query.lat) {
    var coords = [req.query.lon, req.query.lat];
    var maxD = (req.query.maxDistance || 5) / 6371;
    q = q.where('location.geo')
             .near({ center: coords, maxDistance: maxD, spherical:true })
}
q.exec(function(err, items) {
    if (err) return res.apiError('database error', err);
    res.apiResponse({
        events: items
    });
});

KeystoneJS 项目可以具有充当文档功能的方法。虚函数不接受参数(它们用于 calculate/return 基于文档属性的值)。所以这里需要一个模式上的方法。

在您的 Event.js 模型代码中,您需要创建适当的方法来根据存储在当前文档中的坐标计算距离(以公里为单位)。

Event.schema.methods.distanceKM = function (latitude, longitude, cb) {
    return cb(this._.location.kmFrom([longitude, latitude]));
};

这是一个异步实现。如果您t/don不想那样做,请改用它。

Event.schema.methods.distanceKM = function (latitude, longitude) {
    return this._.location.kmFrom([longitude, latitude]);
};

如果您需要结果以英里为单位,只需将方法中的 kmFrom 更改为 milesFrom

然后您可以为每个事件调用距离函数。具体的实现取决于您,但是下面的查询返回的每个项目现在都将具有 distance 函数,该函数 returns 从该事件到参数化的距离(公里或英里)坐标.

重要

我在写这篇文章的过程中发现 kmFrommilesFrom 的当前实现被破坏了。 npm 上的最新版本有这个损坏的代码。 The functions have been updated on GitHub(您可以看到在本地更改的少量代码将使它们工作),但在撰写本文时尚未将其推送到 Keystone 版本中。