MongoDB/Mongoose - 使用geoNear和子文档进行聚合

jor*_*dan 7 javascript geolocation mongoose mongodb aggregation-framework

我正在使用node-geoip模块并执行聚合查询.我执行查询的模式如下所示:

var mongoose = require('mongoose');
require('./location.js');

module.exports = mongoose.model('Region',{
    attr1: Number,
    attr2: String,
    attr3: String,
    locations:[mongoose.model('Location').schema]
});
Run Code Online (Sandbox Code Playgroud)

var mongoose = require('mongoose');

module.exports = mongoose.model('Location',{
    attr1: Number,
    latlong: { type: [Number], index: '2d' },
});
Run Code Online (Sandbox Code Playgroud)

我需要在聚合查询中执行$ geoNear操作,但我遇到了一些问题.首先,这是我的聚合方法:

var region = require('../models/region');

var geo = geoip.lookup(req.ip);

region.aggregate([
    {$unwind: "$locations"},
    {$project: {
        attr1 : 1,
        attr2 : 1,
        locations : 1,
        lower : {"$cond" : [{$lt: [ '$locations.attr1', '$attr1']}, 1, 0]}
    }},
     {
      $geoNear: {
         near: { type:"Point", '$locations.latlong': geo.ll },
         maxDistance: 40000,
         distanceField: "dist.calculated"
      }
     },
    { $sort: { 'locations.attr1': -1 } },
    {$match : {lower : 1}},
    { $limit: 1 }
], function(err,f){...});
Run Code Online (Sandbox Code Playgroud)

我得到的第一个问题是显然geoNear必须处于管道的第一阶段:exception: $geoNear is only allowed as the first pipeline stage.所以我的问题是,我可以在子文档中执行geoNear搜索而不需要展开吗?如果是这样,怎么样?

我得到的另一个错误信息是errmsg: \"exception: 'near' field must be point\".这意味着什么,它对我的​​代码意味着什么?我试过near用作:

near: { type:"Point", '$locations.latlong': geo.ll },
Run Code Online (Sandbox Code Playgroud)

Rob*_*ore 4

首先声明:我不是 Node/Mongoose 专家,所以我希望您可以将通用格式转换为 Node/Mongoose。

对于错误:

 errmsg: "exception: 'near' field must be point"
Run Code Online (Sandbox Code Playgroud)

对于“2d”索引,这不能是GeoJson点,而需要是“旧坐标对”。例如,

 errmsg: "exception: 'near' field must be point"
Run Code Online (Sandbox Code Playgroud)

如果您想使用 GeoJSON,您将需要使用“2dsphere”索引。

通过此更改,$geoNear 查询将使用查询中的点数组。shell 中的一个例子:

{
  "$geoNear": {
    "near": geo.ll,
    "maxDistance": 40000,
    "distanceField": "dist.calculated"
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您只能获得每个文档的单个距离(最近的点),这在语义上与展开然后确定到每个点的距离不同。我无法确定这对您的用例是否重要。