Я использую официальный строго типизированный драйвер 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 в массиве (многоклавишный + геопространственный)
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, у которых есть хотя бы одна точка рядом с данной точкой? И отсортировать их по ближайшему?





Драйвер MongoDB .NET предоставляет класс 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 : "2dsphere" } );
Или через драйвер 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 вы сначала укажите долготу.
Поиск соседей:
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();
MongoDB не поддерживает геопространственные индексы для массивов. Индекс может быть создан для свойства, которое в основном составляет одну точку. Подробности см. В этот вопрос. Если вы хотите использовать MongoDB для поиска ближайших точек, ваш единственный вариант на данный момент - создать отдельный документ MongoDB для каждой точки маршрута и использовать оператор $near, как в ответе выше.
Спасибо за ответ
Хорошо. Что, если местоположение является свойством массива вложенного документа, могу ли я выполнить ближайший запрос. см. мое редактирование для дальнейшего объяснения
Обновления ответа @ 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)
Спасибо за ответ, проблема в том, что поле местоположения представляет собой массив местоположений или, другими словами, маршрут или строку, как с этим выполнить ближайший запрос?