MongoDb C# GeoNear Query Construction

后端 未结 3 834
悲哀的现实
悲哀的现实 2020-12-16 19:15

How do I query MongoDB for nearby geographic points using the C# driver and the GeoNear method?

The following returns points with an incorrect Distance

相关标签:
3条回答
  • 2020-12-16 19:19

    there is no GeoNear method on IMongoCollection anymore in the 2.x driver. here's a strongly typed and easy way to do $geoNear queries using MongoDB.Entities convenience library.

    using MongoDB.Driver;
    using MongoDB.Entities;
    
    namespace StackOverflow
    {
        public class Program
        {
            public class Cafe : Entity
            {
                public string Name { get; set; }
                public Coordinates2D Location { get; set; }
                public double DistanceMeters { get; set; }
            }
    
            private static void Main(string[] args)
            {
                new DB("test");
    
                DB.Index<Cafe>()
                  .Key(c => c.Location, KeyType.Geo2DSphere)
                  .Create();
    
                (new Cafe
                {
                    Name = "Coffee Bean",
                    Location = new Coordinates2D(48.8539241, 2.2913515),
                }).Save();
    
                var searchPoint = new Coordinates2D(48.796964, 2.137456);
    
                var cafes = DB.GeoNear<Cafe>(
                                   NearCoordinates: searchPoint,
                                   DistanceField: c => c.DistanceMeters,
                                   MaxDistance: 20000)
                              .ToList();
            }
        }
    }
    

    the above code sends the following query to mongodb server:

    db.Cafe.aggregate([
        {
            "$geoNear": {
                "near": {
                    "type": "Point",
                    "coordinates": [
                        48.796964,
                        2.137456
                    ]
                },
                "distanceField": "DistanceMeters",
                "spherical": true,
                "maxDistance": NumberInt("20000")
            }
        }
    ])
    
    0 讨论(0)
  • 2020-12-16 19:25

    Found the answer via this and this:

    var earthRadius = 6378.0; // km
    var rangeInKm = 3000.0; // km
    
    myCollection.EnsureIndex(IndexKeys.GeoSpatial("Location"));
    
    var near =
        Query.GT("ExpiresOn", now);
    
    var options = GeoNearOptions
        .SetMaxDistance(rangeInKm / earthRadius /* to radians */)
        .SetSpherical(true);
    
    var results = myCollection.GeoNear(
        near,
        request.Longitude, // note the order
        request.Latitude,  // [lng, lat]
        200,
        options
    );
    
    0 讨论(0)
  • 2020-12-16 19:37

    Here is a working example for driver v2.10+. It uses a correct geospatial point field type and runs $nearSphere query.

    var longitude = 30d; //x
    var latitude= 50d; //y
    var point = new GeoJsonPoint<GeoJson2DGeographicCoordinates>(new GeoJson2DGeographicCoordinates(longitude, latitude));
    var filter = Builders<TDocument>.Filter.NearSphere(doc => doc.YourLocationField, point, maxGeoDistanceInKm * 1000);
    var result = await collection.Find(filter).ToListAsync();
    

    Type of YourLocationField should be GeoJsonPoint<GeoJson2DGeographicCoordinates>. PS. Also you can create an index of your field for faster searching like this:

    collection.Indexes.CreateManyAsync(
        new []
        {
            new CreateIndexModel<TDocument>(Builders<TDocument>.IndexKeys.Geo2DSphere(it => it.YourLocationField))
        }
    );
    
    0 讨论(0)
提交回复
热议问题