使用 C# MongoDB 查询在数据库集合中查找最近的纬度/经度

HaB*_*aBo 5 c# mongodb mongodb-csharp-2.0

我有一个 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
    }
}
Run Code Online (Sandbox Code Playgroud)

我想出了两个地理坐标的远程计算器

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);
        }
Run Code Online (Sandbox Code Playgroud)

有了这个,我可以计算给定坐标到集合中所有坐标的距离形式,并取最近的一个。当我的集合中有数十个文档时,这将起作用。但在这里我有数百万条记录。这种方法将非常痛苦(实际上失败了)。

因此,我需要编写一个 C# MongoDB 驱动程序查询,该查询可以为给定的 x,y 点找到最接近的文档。我在这里看到了 SQL Server 的一个很好的答案。这是一篇很好的文章来做同样的事情,但他们再次在 SQL 查询方法中解释了这一点。我如何为 C# MongoDB 版本提出类似的查询?

我正在使用MongoDB.Driver 2.10.2

更新

在 Mongo 文档geoNear上找到了一种方法,这看起来很酷,但它需要更改我的文档结构(还需要检查索引集合需要多长时间。因为我的集合每隔一小时就会更新/更换一次)。可以说,我将继续更改我的文档结构,是否有 C# MongoDB 驱动程序查询方式的参考?而不是 Mongo Shell 脚本?

更新(可以提出查询)


最后,我对文档结构进行了更改以符合 GEOJSON 并添加了 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();
Run Code Online (Sandbox Code Playgroud)

只要查询为空,此代码就可以工作

{ "query", new BsonDocument() }
Run Code Online (Sandbox Code Playgroud)

如果我将查询更改如下,它会失败

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

例外:

MongoCommandException:命令聚合失败:无法确定查询系统是否可以提供覆盖的投影 :: 由 :: 未知顶级运算符引起:$gt。