$ geowithin: $ polygon не использует индекс 2dsphere

У меня есть коллекция следующих документов:

{
    "_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, он использует 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]
        ]]
      }}
    }})

Есть ли причина, по которой в первом запросе не используется индекс? В руководстве Mongo об этом ничего не говорится. Можете ли вы указать мне, что делать, чтобы использовать $ polygon для поиска по индексу, или мне нужно переписать все запросы в моем приложении, чтобы использовать $ geometry. Я использую драйвер C#, синтаксис которого выглядит так:

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

Однако это создает первый запрос, который не использует index.

Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
0
797
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я не работаю на mongo, поэтому не буду рисковать догадываться, что Почему (помимо устаревших и новых моделей данных) сбивает с толку новичков, но здесь как mongo различает индекс бесконечный-плоский-2d ($ polygon query) и индекс сферический (запрос $ geometry)

передача $ polygon нацелена на унаследованный 2d-индекс, где или $ геометрия нацелена на 2d-сферический индекс. Mongo разделяет эти запросы на два разных типа объектов.

здесь: https://github.com/mongodb/mongo/blob/master/src/mongo/db/geo/geoparser.cpp#L785-L790

Mongo действительно говорит, что индекс 2dsphere доступен для Только через запрос $ геометрия (а не устаревший запрос $ polygon)

здесь: https://docs.mongodb.com/manual/tutorial/query-a-2dsphere-index/

Как вы отметили: Mongo очень полезен тем, что может возвращать данные, даже если вы не соответствовали своим запросам.


Почему $ polygon вообще больше не существует?

Mongo продолжает поддерживать несферические двумерные индексы для тех, кому нужен двумерный индекс на бесконечной плоской поверхности. Возможно, для видеоигр или для любого использования, где бесконечная плоская поверхность является достаточно хорошим приближением, чтобы избежать математики с плавающей запятой (и связанных вопросов округления)

описано здесь: https://docs.mongodb.com/manual/tutorial/query-a-2d-index/

Хорошо, и я просто добавляю ответ на C#.

Новый запрос:

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

И мой вспомогательный класс для rectangle.To GeoJson Polygon ():

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));
        }
    }

Другие вопросы по теме