我有一个用node.js mongodb和mongoose实现的地理数据api。 我想用两个标准来查询我的数据。
首先,我使用geoNear获取给定半径内的所有位置,这样可以正常工作。 其次,我想进一步按类型过滤位置。
这是我的架构:
var GeoLocationSchema = new Schema({
name: String,
type: String,
loc: {
type: {
type: String,
required: true,
enum: ["Point", "LineString", "Polygon"],
default: "Point"
},
coordinates: [Number]
}
});
// ensure the geo location uses 2dsphere
GeoLocationSchema.index({ loc : "2dsphere" });
这是我的geoNear查询:
router.route("/locations/near/:lng/:lat/:type/:max")
// get locations near the get params
.get(function(req, res) {
// setup geoJson for query
var geoJson = {};
geoJson.type = "Point";
geoJson.coordinates = [parseFloat(req.params.lng), parseFloat(req.params.lat)];
// setup options for query
var options = {};
options.spherical = true;
options.maxDistance = parseInt(req.params.max)/6370000;
// query db with mongoose geoNear wrapper
GeoLocation.geoNear(geoJson, options, function (err, results, stats) {
if (err)
res.send(err);
res.json(results);
});
});
是否有可能将geoNear查询与特定类型位置的查询相结合,还是可以以某种方式过滤结果?
提前致谢。
答案 0 :(得分:4)
只要您的MongoDB服务器足够新,是2.6或更高版本,那么此功能实际上已移至常规查询引擎。这里的mongoose方法包含了.runCommand()
表单,该表单在以后的所有版本中都被认为已弃用,因此只需要在标准查询中添加其他运算符即可。
GeoLocation.find({
"$nearSphere": {
"$geometry": {
"type": "Point",
"coordinates": [parseFloat(req.params.lng), parseFloat(req.params.lat)]
},
"$maxDistance": distanceInMeters
},
"loc.type": "Point"
},function(err,docs) {
// The documents are also mongoose document objects as well
});
有关选项,请参阅$nearSphere
或其他运营商的更多选项。这里的主要区别是$maxDistance
以米为单位,当使用GeoJSON表格时,而不是其他地方的弧度。
聚合管道当然也有$geoNear
运算符。这可以从MongoDB 2.4开始使用,并且可以采用其他选项(例如“查询”)来进一步缩小结果。这里的另一个可能的优点是它会将一个字段“投影”到表示与查询点“距离”的结果中。这可以用于其他计算或自定义排序:
GeoLocation.aggregate(
[
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [parseFloat(req.params.lng), parseFloat(req.params.lat)]
},
"distanceField": "distance",
"maxDistance": distanceInMeters,
"spherical": true,
"query": { "loc.type": "Point" }
}},
{ "$sort": { "distance": -1 } } // Sort nearest first
],
function(err,docs) {
// These are not mongoose documents, but you can always cast them
}
);
需要注意的其他差异是,在标准查询表单中,结果不再限于100个文档,因为它们是“命令”形式。默认情况下,聚合$geoNear
将100个文档限制为结果,但可以使用管道命令的附加“限制”选项调整返回的文档数。除了从搜索返回的最大文档之外,聚合语句不“排序”结果是给定条件的最高结果,但它们不按顺序返回,因此您需要按照显示对它们进行排序。
在任何一种情况下,您都应该将代码移动到使用这些表单中的任何一种,因为命令表单被认为已弃用,将来会被删除。 mongoose API是否将其方法保留为其中一种形式的“包装”尚不清楚,但大多不太可能,因此最好坚持使用受支持的表单。
答案 1 :(得分:2)
您可以将附加查询作为选项传递给mongoose geoNear函数,如下所示:
// setup geoJson for query
var geoJson = {};
geoJson.type = "Point";
geoJson.coordinates = [parseFloat(req.params.lng), parseFloat(req.params.lat)];
// setup options for query
var options = {};
options.spherical = true;
options.maxDistance = parseInt(req.params.max)/6370000;
// you can put any query here to further refine the result.
options.query = { "loc.type": "Point" };
// query db with mongoose geoNear wrapper
GeoLocation.geoNear(geoJson, options, function (err, results, stats) {
if (err)
res.send(err);
res.json(results);
});