将 geoNear 查询与另一个查询组合以获取值
Posted
技术标签:
【中文标题】将 geoNear 查询与另一个查询组合以获取值【英文标题】:combine geoNear query with another query for a value 【发布时间】:2014-10-24 09:50:31 【问题描述】:我有一个使用 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 查询与特定类型位置的查询结合起来,或者我可以以某种方式过滤结果?
提前致谢。
【问题讨论】:
使用$geoNear
聚合阶段作为管道中的第一阶段。您可以使用$match
阶段等进行进一步的条件/操作。
【参考方案1】:
只要您的 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 是否将其方法保留为这些表单之一的“包装器”尚不清楚,但几乎不可能,因此最好坚持使用受支持的表单。
【讨论】:
感谢您提供如此详细的回答!【参考方案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);
);
【讨论】:
以上是关于将 geoNear 查询与另一个查询组合以获取值的主要内容,如果未能解决你的问题,请参考以下文章
$near 错误 - 规划器返回错误:无法找到 $geoNear 查询的索引