$ geowithin:$ polygon不使用2dsphere索引

时间:2018-10-29 15:55:17

标签: mongodb indexing mongodb-query geospatial bson

我正在收集如下文件:

{
    "_id" : ObjectId("5bc15f23d672e9086ca4fbac"),
    "Location" : {
        "GeoJson" : {
            "type" : "Point",
            "coordinates" : [14.4199254356, 50.0700249768]
        }
}

我创建了如下索引

{ Location.GeoJson2dsphere : "2dsphere" }

现在当我使用$polygon进行搜索时出现了问题,我得到了结果,但是查询未使用索引,因此速度很慢。这是查询

.find({"Location.GeoJson" : {
      "$geoWithin" : {
      "$polygon" : [ 
        [14.4182910543168, 50.0891393887804], 
        [14.4491901021683, 50.0891393887804], 
        [14.4491901021683, 50.0671069088523], 
        [14.4182910543168, 50.0671069088523]
      ]
    }
  }
})

但是当我改用$ Geometry时,它使用的是索引。

.find({"Location.GeoJson" : {
  "$geoWithin" : 
    {"$geometry" :
      {"type" : "Polygon",
        "coordinates" : [[ 
          [14.4182910543168, 50.0891393887804], 
          [14.4491901021683, 50.0891393887804], 
          [14.4491901021683, 50.0671069088523], 
          [14.4182910543168, 50.0671069088523],
          [14.4182910543168, 50.0891393887804]
        ]]
      }}
    }})

是否有任何原因导致第一个查询不使用索引? Mongo手册对此没有说什么。 您能指出我,使用$ polygon搜索索引该怎么做,还是我需要重写我应用程序中的所有查询才能使用$ geometry。我正在使用C#驱动程序,其语法如下所示:

Builders<Offer>.Filter.GeoWithinPolygon(a => a.Location.GeoJson, polygon);

但是,这是第一个查询,它不使用索引。

2 个答案:

答案 0 :(得分:1)

我不为mongo工作,所以不会冒险猜测为什么(除了旧数据模型还是新数据模型)使新人感到困惑,但这是方法 mongo区分 infinite-flat-2d ($多边形查询)索引和 球形 索引( $ geometry查询)

传递 $ polygon 会针对旧版2d索引,而 $ geometry 会针对2d球形索引。 Mongo将这些查询分为两种不同的对象类型

此处:https://github.com/mongodb/mongo/blob/master/src/mongo/db/geo/geoparser.cpp#L785-L790

Mongo确实说只能通过 $ geometry 查询(不是传统的 $ polygon 查询)只能访问2dsphere索引

>

此处:https://docs.mongodb.com/manual/tutorial/query-a-2dsphere-index/

如您所述: Mongo非常有帮助,即使您不匹配查询,它仍然可以返回数据。


为什么 $ polygon 甚至不再是东西?

对于那些希望在无限的平面上使用2d索引的人,Mongo继续支持非球形2d索引。也许是用于视频游戏,或者用于无限平坦的平面足以避免浮点数学运算(以及相关的舍入问题)的任何用途

此处描述:https://docs.mongodb.com/manual/tutorial/query-a-2d-index/

答案 1 :(得分:0)

好,我只是在C#中添加aswer。

新查询为:

GeoJsonPolygon<GeoJson2DCoordinates> polygon;
var filter = Builders<Offer>.Filter.GeoWithin(a => a.Location.GeoJson, polygon);

还有我的矩形帮助类。ToGeoJsonPolygon():

public class Rectangle
    {
        public double StartX { get; set; }
        public double StartY { get; set; }
        public double EndX { get; set; }
        public double EndY { get; set; }

        public double[,] ToCoordinates()
        {
            var retval = new double[4, 2];
            retval[0, 0] = this.StartX;
            retval[0, 1] = this.StartY;
            retval[1, 0] = this.EndX;
            retval[1, 1] = this.StartY;
            retval[2, 0] = this.EndX;
            retval[2, 1] = this.EndY;
            retval[3, 0] = this.StartX;
            retval[3, 1] = this.EndY;

            return retval;
        }

        public GeoJsonPolygon<GeoJson2DCoordinates> ToGeoJsonPolygon()
        {
            return GeoJson.Polygon(
                GeoJson.Position(StartX, StartY),
                GeoJson.Position(EndX, StartY),
                GeoJson.Position(EndX, EndY),
                GeoJson.Position(StartX, EndY),
                GeoJson.Position(StartX, StartY));
        }
    }