当前文档字段值内的地理空间 $near

ana*_*ius 1 geospatial mongodb mongodb-query aggregation-framework spring-mongodb

采取这个查询:

{ 'location' : { '$near' : [x,y], '$maxDistance' : this.field } }
Run Code Online (Sandbox Code Playgroud)

我想将当前评估文档中指定字段的值分配给 $maxDistance 。那可能吗?

Nei*_*unn 5

是的,这是可能的。你只要用$geoNear它来代替。当心陷阱并仔细阅读。

假设您的意图是存储一个字段,以便"travelDistance"在文档上指示任何此类搜索必须在距查询点所提供的距离“范围内”才有效。然后我们简单地查询并评估条件$redact

db.collection.aggregate([
  { "$geoNear": {
    "near": { 
      "type": "Point",
      "coordinates": [x,y]
    },
    "spherical": true,
    "distanceField": "distance"
  }},
  { "$redact": {
    "$cond": {
      "if": { "$lte": [ "$distance", "$travelDistance" ] },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])
Run Code Online (Sandbox Code Playgroud)

唯一的问题是,$geoNear就像$near一开始只会返回一定数量的“附近”文档。您可以使用选项进行调整,但与一般查询形式不同,这基本上保证最终返回的结果将小于指定的“最近”数字。

只要你意识到这一点,那么这就是完全正确的。

事实上,这是处理限定半径内“附近”的内容的一般方法。

另请注意根据坐标存储方式的“距离”。作为传统坐标对,距离将以弧度为单位,您可能需要进行数学计算才能将其转换为公里或英里。

如果使用 GeoJSON,则距离始终以米为单位,作为标准格式。

所有数学笔记都在文档中。

注意:请仔细阅读$geoNear文档。"spherical"索引需要类似的选项"2dsphere",例如现实世界坐标应该有的选项。还"limit"可能需要应用以增加超过默认的 100 个文档结果,以便进一步修剪。


由于评论提到了 spring mongo,那么这里基本上做了同样的事情:

Aggregation aggregation = newAggregation(
    new AggregationOperation() {
      @Override
      public DBObject toDBObject(AggregationOperationContext context) {
        return new BasicDBObject("$geoNear",
          new BasicDBObject(
            "near", new BasicDBObject(
              "type","Point")
              .append("coordinates", Arrays.asList(20,30))
            )
            .append("spherical",true)
            .append("distanceField","distance")
          );
        }
    },
    new AggregationOperation() {
      @Override
      public DBObject toDBObject(AggregationOperationContext context) {
        return new BasicDBObject("$redact",
          new BasicDBObject(
            "$cond", Arrays.asList(
               new BasicDBObject("$lte", Arrays.asList("$distance", "$travelDistance")),
               "$$KEEP",
               "$$PRUNE"
             )
          )
       );
     }
    }
);
Run Code Online (Sandbox Code Playgroud)