我正在使用官方C#MongoDb强类型驱动程序版本2.5.0与MongoDB进行交互。
我有一个经度和纬度坐标数组,我想将它们存储在MongoDB中。
用于存储坐标数组的类的名称是什么?所以我最近可以做以下查询,检查如果一个给定的坐标靠近坐标数组中的任何一点,如何实现呢?
这是一个展示问题的简单代码。
var coordinates = new List<(double latitude, double longitude)>();
//Store coordinates array in the database
(double latitude, double longitude) point = (-33.847927, 150.6517805);
int maxDistance = 300;//Max Distance in meters
//Check if any point in the coordinates array is 300 m near the given point
修改: -
根据以下@CodeFuller评论中提到的这个问题: -
MongoDB geospatial index on an array (multikey + geospatial)
MongoDB不支持数组上的地理空间索引,因此请考虑以下类:
class SomeDocument {
public ObjectId Id { get; set; }
public string Title { get; set; }
public List<MyClass> Locations {get; set;} = new List<MyClass>();
}
class MyClass {
public ObjectId Id { get; set; }
public GeoJsonPoint<GeoJson2DGeographicCoordinates> Location { get; set;
}
如何让SomeDocument的所有实例至少在给定点附近有一个点?并按最近的一个排序?
答案 0 :(得分:3)
MongoDB .NET驱动程序为2D地理坐标提供MongoDB.Driver.GeoJsonObjectModel.GeoJson2DGeographicCoordinates
类。
以下是基本用法:
在模型类中,使用GeoJsonPoint<GeoJson2DGeographicCoordinates>
类型定义属性:
public class SomeDocument
{
public ObjectId Id { get; set; }
public string Title { get; set; }
public GeoJsonPoint<GeoJson2DGeographicCoordinates> Location { get; set; }
}
确保2dsphere
字段的2d
(或Location
,取决于您的需求)索引。您可以通过mongo客户端创建和索引:
db.testCollection.createIndex({Location:&#34; 2dsphere&#34;});
或通过MongoDB .NET驱动程序:
var database = mongoClient.GetDatabase("testDB");
IMongoCollection<SomeDocument> collection = database.GetCollection<SomeDocument>("testCollection");
collection.Indexes.CreateOne(new IndexKeysDefinitionBuilder<SomeDocument>().Geo2DSphere(x => x.Location));
插入数据:
collection.InsertOne(new SomeDocument
{
Title = "Place #1",
Location = GeoJson.Point(new GeoJson2DGeographicCoordinates(145.89, -35.83)),
});
collection.InsertOne(new SomeDocument
{
Title = "Place #2",
Location = GeoJson.Point(new GeoJson2DGeographicCoordinates(154.98, -53.38)),
});
请注意,在MongoDB中,您specify longtitude first。
寻找邻居:
var point = GeoJson.Point(new GeoJson2DGeographicCoordinates(145.889, -35.831));
int maxDistance = 300;
IAsyncCursor<SomeDocument> cursor = collection.FindSync(new FilterDefinitionBuilder<SomeDocument>().Near(x => x.Location, point, maxDistance: maxDistance));
// Check whether at least one is near the point
var hasNeighbors = cursor.Any();
答案 1 :(得分:0)
更新为@CodeFuller的答案。
第2点。
CreateOne( new IndexKeysDefinitionBuilder..)
已贬值。而是使用CreateOne( new CreateIndexModel()...
。
方法如下:
collection.Indexes.CreateOne(
new CreateIndexModel<TDocument>(
new IndexKeysDefinitionBuilder<TDocument>().Geo2DSphere(x => x.Location)));
稍后,我创建了一个通用函数来在启动时创建索引,如下所示:
public CreateIndexes CreateGeoSpatialIndex<TDocument>(Expression<Func<TDocument, object>> field, string collectionName)
{
var collection = _database.GetCollection<TDocument>(collectionName);
try
{
collection.Indexes.CreateOne(
new CreateIndexModel<TDocument>(
new IndexKeysDefinitionBuilder<TDocument>().Geo2DSphere(field)));
}
catch (Exception ex) when (ex.Message.Contains("already exists"))
{
// Log info
}
return this;
}
第4点。
此外,Near()对我不起作用,而是在查询时必须使用NearSphere()。
var filterDefinition = new FilterDefinitionBuilder<T>().NearSphere(x => x.Location, lng, lat, maxdistance)