Найти ближайшую широту / долготу в коллекции БД с помощью запроса C# MongoDB - PullRequest
5 голосов
/ 09 марта 2020

У меня есть коллекция MongoDB, в которой хранятся миллионы записей, как показано ниже

{ 
    "_id" : ObjectId("5e662d6e9ce8bf144c715afd"), 
    "X" : 19.229000091552734, 
    "Y" : 233.723388671875,  
    "Data" : {
       // Some data
    }
}
{ 
    "_id" : ObjectId("5e662d6e9ce8bf144c715afe"), 
    "X" : 19.229000091552734, 
    "Y" : 2773.426513671875, 
    "Data" : {
        // Some data
    }
}

Я разработал удаленный калькулятор для двух GeoCoordindates

public static double DistanceTo(this Coordinates baseCoordinates, Coordinates targetCoordinates, UnitOfLength unitOfLength)
        {
            var baseRad = Math.PI * baseCoordinates.Latitude / 180;
            var targetRad = Math.PI * targetCoordinates.Latitude / 180;
            var theta = baseCoordinates.Longitude - targetCoordinates.Longitude;
            var thetaRad = Math.PI * theta / 180;

            double dist =
                Math.Sin(baseRad) * Math.Sin(targetRad) + Math.Cos(baseRad) *
                Math.Cos(targetRad) * Math.Cos(thetaRad);
            dist = Math.Acos(dist);

            dist = dist * 180 / Math.PI;
            dist = dist * 60 * 1.1515;

            return unitOfLength.ConvertFromMiles(dist);
        }

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

Итак, мне нужно написать запрос C# MongoDB Driver, который может найти ближайший документ для получения точек x, y. Я вижу хороший ответ для SQL Сервер здесь . Вот хорошая статья , которая делает то же самое, но они снова объясняют это в SQL подходе к запросу. Как мне создать аналогичный запрос для C# MongoDB версии?

Я использую MongoDB.Driver 2.10.2

Обновление

Нашел подход в документации Mon go, geoNear , это выглядит круто, но требует изменений в структуре моего документа (также необходимо проверить, сколько времени будет индексировать коллекцию. Поскольку моя коллекция постоянно обновляется / заменяется каждый час). Допустим, я go опередил внесение изменений в структуру моего документа, есть ли ссылка на способ запроса драйвера C# MongoDB? вместо понедельника go сценарий оболочки?

Обновление (может появиться запрос)


Наконец я внес изменения в структуру своего документа в соответствии с GEO JSON и добавленный индекс 2dsphere

Вот мой запрос

               var geoNearOptions = new BsonDocument
                            {
                                //{"near",new BsonArray(new Double[]{longitude,latitude})},
                                 {"near",new BsonDocument{
                                     { "type", "Point" },
                                     { "coordinates",
                                        new BsonArray(new Double[] { longitude, latitude }) } } } ,
                                {"distanceField","dist.calculated"},
                                //{"distanceMultiplier",  (2.00).NauticalMilesToMeters().MetersToKiloMeters() },
                                {"maxDistance",  (2.00).NauticalMilesToMeters().MetersToKiloMeters() },
                                { "query", new BsonDocument() },
                                {"includeLocs","dist.location" },
                                {"allowDiskUse",true},
                                {"spherical", true}
                            };
            var geonear = new BsonDocument { { "$geoNear", geoNearOptions } };
            //var stage = new BsonDocumentPipelineStageDefinition<BsonDocument, BsonDocument>(new BsonDocument { { "$geoNear", geoNearOptions } });
            var colAggregate = _myCollection.Aggregate().AppendStage<NationalBlendModel>(geonear)
                .Limit(3)
                .ToList();

Этот код работает, пока запрос пуст

{ "query", new BsonDocument() }

, если я изменю запрос как под ним происходит сбой

var filter = new BsonDocument { { "$gt", new BsonArray { "validTime", new BsonDateTime(DateTime.Now) } } };
{ "query", filter }

Исключение:

MongoCommandException: Совокупность команд не выполнена: не удалось определить, может ли система запросов предоставить покрытую проекцию ::, вызванную :: неизвестным оператором верхнего уровня : $ gt.

...