MongoDB/Mongoose - 与 geoNear 和子文档的聚合
MongoDB/Mongoose - Aggregation with geoNear & subdocuments
我正在使用 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]
});
和
var mongoose = require('mongoose');
module.exports = mongoose.model('Location',{
attr1: Number,
latlong: { type: [Number], index: '2d' },
});
我需要在聚合查询中执行 $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){...});
我遇到的第一个问题显然是 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 },
首先免责声明:我不是 Node/Mongoose 专家,所以我希望您能将通用格式转换为 Node/Mongoose。
对于错误:
errmsg: "exception: 'near' field must be point"
对于“2d”索引,这不能是 GeoJson 点,而需要是 "legacy coordinate pair"。例如,
{
"$geoNear": {
"near": geo.ll,
"maxDistance": 40000,
"distanceField": "dist.calculated"
}
}
如果您想使用 GeoJSON,您将需要使用“2dsphere”索引。
通过该更改,$geoNear 查询将使用查询中的点数组。 shell中的示例:
> db.test.createIndex({ "locations": "2d" })
> db.test.insert({ "locations": [ [1, 2], [10, 20] ] });
> db.test.insert({ "locations": [ [100, 100], [180, 180] ] });
> db.test.aggregate([{
"$geoNear": {
"near": [10, 10],
"maxDistance": 40000,
"distanceField": "dist.calculated",
num: 1
}
}]);
{
"result": [{
"_id": ObjectId("552aaf7478dd9c25a3472a2a"),
"locations": [
[
1,
2
],
[
10,
20
]
],
"dist": {
"calculated": 10
}
}],
"ok": 1
}
请注意,每个文档(最近点)只能得到一个距离,这在语义上与展开然后确定到每个点的距离不同。我不确定这对您的用例是否重要。
我正在使用 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]
});
和
var mongoose = require('mongoose');
module.exports = mongoose.model('Location',{
attr1: Number,
latlong: { type: [Number], index: '2d' },
});
我需要在聚合查询中执行 $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){...});
我遇到的第一个问题显然是 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 },
首先免责声明:我不是 Node/Mongoose 专家,所以我希望您能将通用格式转换为 Node/Mongoose。
对于错误:
errmsg: "exception: 'near' field must be point"
对于“2d”索引,这不能是 GeoJson 点,而需要是 "legacy coordinate pair"。例如,
{
"$geoNear": {
"near": geo.ll,
"maxDistance": 40000,
"distanceField": "dist.calculated"
}
}
如果您想使用 GeoJSON,您将需要使用“2dsphere”索引。
通过该更改,$geoNear 查询将使用查询中的点数组。 shell中的示例:
> db.test.createIndex({ "locations": "2d" })
> db.test.insert({ "locations": [ [1, 2], [10, 20] ] });
> db.test.insert({ "locations": [ [100, 100], [180, 180] ] });
> db.test.aggregate([{
"$geoNear": {
"near": [10, 10],
"maxDistance": 40000,
"distanceField": "dist.calculated",
num: 1
}
}]);
{
"result": [{
"_id": ObjectId("552aaf7478dd9c25a3472a2a"),
"locations": [
[
1,
2
],
[
10,
20
]
],
"dist": {
"calculated": 10
}
}],
"ok": 1
}
请注意,每个文档(最近点)只能得到一个距离,这在语义上与展开然后确定到每个点的距离不同。我不确定这对您的用例是否重要。