$geowithin:$polygon doesn't use 2dsphere index

风格不统一 提交于 2019-12-13 04:12:05

问题


I am having a collection of documents like following:

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

And I have Index created as following

{ Location.GeoJson2dsphere : "2dsphere" }

And now to the problem when I use the $polygon for searching, i've got the results, but query is not using index, so it's slow. Here is the query

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

But when I use $Geometry instead, it is using index.

.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]
        ]]
      }}
    }})

Is there any reason why the first query isn't using the index? Mongo manual is not saying anything about this. Can you point me, what to do to use $polygon for searching index, or do I need to rewrite all the queries in my app, to use $geometry. I am using C# driver where the syntax looks like this:

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

However, this is producingf the first query, which is not using index.


回答1:


I don't work for mongo, so won't hazard a guess as to why (beyond legacy vs new data models) being confusing for newcomers, but here is how mongo differentiates between an infinite-flat-2d ($polygon query) index and a spherical index ($geometry query)

passing a $polygon targets a legacy 2d index, where or a $geometry targets the 2d-spherical index. Mongo splits out these queries to two different object types

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

Mongo does say that the 2dsphere index is only accessable though a $geometry query (not the legacy $polygon query)

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

As you noted: Mongo is super helpful in that it can still return data, even if you've mismatched your queries.


Why is $polygon even a thing anymore?

Mongo continues to support non-spherical 2d indexes for those that want a 2d index on an infinite flat surface. Perhaps for video games or for any use where an infinite flat surface is a good enough approximation to avoid floating point math (and associated rounding questions)

described here:https://docs.mongodb.com/manual/tutorial/query-a-2d-index/




回答2:


Ok, and I just add the aswer in C#.

The new query is:

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

And my helper class for rectangle.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));
        }
    }


来源:https://stackoverflow.com/questions/53049304/geowithinpolygon-doesnt-use-2dsphere-index

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!