虽然有点尴尬,但有可能与aggregate()
及其$geoNear
运营商合作。令人尴尬的是,因为聚合只允许一个$geoNear
,它必须位于聚合管道的顶部。所以,我们必须做两个聚合,然后合并结果。
想法:$geoNear
将返回给定点与“loc”路径中每个点的距离。然后,我们可以采用最小距离,通过$cond
运营商进行测试,无论它是否在distanceDeviation
之内,并在这种情况下返回文档。
结果是一组匹配第一个点的文档。然后重复其他点的操作,然后将两个数组合并到出现在两个数组中的文档列表中。
这是如何工作的(为了更好的可读性,我用其他的坐标)
db.xx.drop();
db.xx.insert({ distanceDeviation: 2.0, loc: [ [0,0], [10,-10], [20,10], [30,0] ] });
db.xx.insert({ distanceDeviation: 0.1, loc: [ [0,0], [10,-10], [20,10], [30,0] ] });
db.xx.ensureIndex({ loc: "2d" });
db.xx.find();
// points to query:
pointA = [1,1]
pointB = [21,11]
aggA = db.xx.aggregate([
{ $geoNear: { near: pointA, distanceField: "dist" } },
{ $group: { _id: { oid: "$_id", dev: "$distanceDeviation" }, min: { $min: "$dist" } } },
{ $project: { oid: "$_id.oid", isNear: { $cond: [ { $lt: [ "$min", "$_id.dev" ] }, 1, 0 ] }, _id: 0 } },
{ $match: { isNear: 1 } },
]);
aggB = db.xx.aggregate([
{ $geoNear: { near: pointB, distanceField: "dist" } },
{ $group: { _id: { oid: "$_id", dev: "$distanceDeviation" }, min: { $min: "$dist" } } },
{ $project: { oid: "$_id.oid", isNear: { $cond: [ { $lt: [ "$min", "$_id.dev" ] }, 1, 0 ] }, _id: 0 } },
{ $match: { isNear: 1 } },
]);
print("\nObjects with point near route:\n");
aggA.result.forEach(function(a) {
aggB.result.forEach(function(b) {
if (a.oid.toString == b.oid.toString) { print(a.oid) };
});
// Note: this can be optimised
});
结果是:
> db.xx.find()
{ "_id" : ObjectId("5161da88ab49f42c329f4228"), "distanceDeviation" : 2, "loc" : [ [ 0, 0 ], [ 10, -10 ], [ 20, 10 ], [ 30, 0 ] ] }
{ "_id" : ObjectId("5161da88ab49f42c329f4229"), "distanceDeviation" : 0.1, "loc" : [ [ 0, 0 ], [ 10, -10 ], [ 20, 10 ], [ 30, 0 ] ] }
>> // run the aggregates
Objects with point near route:
ObjectId("5161da88ab49f42c329f4228")
另一种完全不同的办法是“画”一个围绕距离“distanceDeviation”的路线封闭多边形,并将其存储在文档中。这将允许搜索$within: $polygon
(类似于您在圈内的搜索),并且还会为靠近路线但不一定靠近其构成点之一的点返回匹配。
请参阅manual的更多信息,aggregate(),$geoNear和$polygon
没有,也没办法)来传递一个变量来查找(这是基于文档中的字段。我不推荐在其他许多方面使用$ where性能原因 - 如果你展开这些数据代表的是什么,也许有不同的方式来构造数据(如果你有这个选项),以获得你想要的定期查询? – 2013-03-19 16:17:46
有可能重构文档。本文档中的loc变量仅表示路线,distanceDeviation表示该路线允许多少灵活性。我应该检查另一个startPoint,endPoint是否在这条路线内。 – 2013-03-19 16:44:13