Asp.Net Core MongoDB 空间定位(点)与距离检索

一:我们先准备点数据

采用高德坐标系来拾取点数 (https://lbs.amap.com/tools/picker)

注意:要注册成开发者,否则拾取到的经纬度只精确到2位

第一百货 119.647437,29.083693
欧景名城 119.639798,29.080843
金华网络经济中心 119.644604,29.074617
金华市第十五中学 119.652758,29.075029
金磐医院 119.642716,29.072554
龙腾江南建材市场 119.636579,29.072366
宝莲广场 119.644433,29.079568
新世纪大厦 119.655548,29.08088
泰地世璟园 119.658809,29.073379
美兰湖公馆 119.639497,29.06824
西京大厦 119.63645,29.081855
星月花园 119.635592,29.078292
兰溪街商业步行街 119.649325,29.082606
阳光城市花园 119.666963,29.082456
华园小区 119.666491,29.073604
印象城 119.658509,29.070716


地理位置

二:把数据存到mongodb中,便于后面使用

db.mapinfo.insert({"address": "第一百货", "name":"第一百货", "location": {"type": "Point", "coordinates": [119.647437,29.083693]}})
db.mapinfo.insert({"address": "欧景名城", "name":"欧景名城", "location": {"type": "Point", "coordinates": [119.639798,29.080843]}})
db.mapinfo.insert({"address": "金华网络经济中心", "name":"金华网络经济中心", "location": {"type": "Point", "coordinates": [119.644604,29.074617]}})
db.mapinfo.insert({"address": "金华市第十五中学", "name":"金华市第十五中学", "location": {"type": "Point", "coordinates": [119.652758,29.075029]}})
db.mapinfo.insert({"address": "金磐医院", "name":"金磐医院", "location": {"type": "Point", "coordinates": [119.642716,29.072554]}})
db.mapinfo.insert({"address": "龙腾江南建材市场", "name":"龙腾江南建材市场", "location": {"type": "Point", "coordinates": [119.636579,29.072366]}})
db.mapinfo.insert({"address": "宝莲广场", "name":"宝莲广场", "location": {"type": "Point", "coordinates": [119.644433,29.079568]}})
db.mapinfo.insert({"address": "新世纪大厦", "name":"新世纪大厦", "location": {"type": "Point", "coordinates": [119.655548,29.08088]}})
db.mapinfo.insert({"address": "泰地世璟园", "name":"泰地世璟园", "location": {"type": "Point", "coordinates": [119.658809,29.073379]}})
db.mapinfo.insert({"address": "美兰湖公馆", "name":"美兰湖公馆", "location": {"type": "Point", "coordinates": [119.639497,29.06824]}})
db.mapinfo.insert({"address": "西京大厦", "name":"西京大厦", "location": {"type": "Point", "coordinates": [119.63645,29.081855]}})
db.mapinfo.insert({"address": "星月花园", "name":"星月花园", "location": {"type": "Point", "coordinates": [119.635592,29.078292]}})
db.mapinfo.insert({"address": "兰溪街商业步行街", "name":"兰溪街商业步行街", "location": {"type": "Point", "coordinates": [119.649325,29.082606]}})
db.mapinfo.insert({"address": "阳光城市花园", "name":"阳光城市花园", "location": {"type": "Point", "coordinates": [119.666963,29.082456]}})
db.mapinfo.insert({"address": "华园小区", "name":"华园小区", "location": {"type": "Point", "coordinates": [119.666491,29.073604]}})
db.mapinfo.insert({"address": "印象城", "name":"印象城", "location": {"type": "Point", "coordinates": [119.658509,29.070716]}})

一定要加索引

mongodb 提供的地图索引有两种,分别是 2d 和 2dsphere。

2d 索引通过二维平面记录点坐标,支持在平面几何中计算距离,而 2dsphere 则支持在球面上进行距离的计算,并且支持 mongodb 的所有地理空间查询方法。

简单的理解,2dsphere 是 2d 的增强版。根据官方推荐,如果你的mongodb版本大于2.6

db.mapinfo.ensureIndex({location : "2dsphere"})

数据库数据


假设当前位置在“1921文化创意园” 具体坐标 119.627438,29.078988

当前位置

检索规定半径以内数据(单位为米)

这里取2000米

db.mapinfo.find({location: {$near: {$geometry: {type: "Point", coordinates: [119.627438,29.078988]}, $maxDistance: 2000}}})

或者

db.mapinfo.find({location: {$nearSphere: {$geometry: {type: "Point", coordinates: [119.627438,29.078988]}, $maxDistance: 2000}}})


查询结果,由近到远


按照离我最近排序,除了使用 $nearSphere 查询外,我们还可以使用 aggregate 来实现。

使用 aggregate 有两个好处。

1.我们在进行排序的后,可以返回两点之间的距离。

2.我们可以进行更为复杂的排序,例如我们可以先根据某个字段进行排序,然后该字段相同的情况下再根据距离排序。

db.mapinfo.aggregate([
   {
     $geoNear: {
        near: {type: "Point", coordinates: [119.627438,29.078988]},
        distanceField: "distance",
        spherical: true,       
        maxDistance: 15000,
				query: {
			    address: {$regex:'建材'}
				}
     }
   },
   { $skip: 0 },
   { $limit: 2 }
])


aggregate 查询


如果我们希望查询以某个点为中心的圆几公里以内的数据,那你可以如下操作:

地球表面1弧度距离约为6378137米, 0.001弧度距离为6378米

db.mapinfo.find({
    "location": {
        "$geoWithin": {
            "$centerSphere": [
                [
                    119.627438,29.078988
                ],
                0.025 // 单位为弧度
            ]
        }
    }
})


以某个点为中心的圆几公里以内的数据


写到这里,其实已经实现了基于MongoDB 空间定位(点)与距离检索

那.net中代码如何实现,看下面具体说明。

编写实体对象 mapinfo

public class mapinfo
    {
        /// 
        /// 主键
        /// 
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string id { get; set; }

        /// 
        /// 地址
        /// 
        public string address { get; set; }
        /// 
        /// 社区名称
        /// 
        public string name { get; set; }

        /// 
        /// 距离
        /// 
        public double? distance { get; set; }

        /// 
        /// 经纬度坐标
        /// 
        public GeoJsonPoint location { get; set; }
    }

IMapinfoMongoRepository

 public interface IMapinfoMongoRepository
    {
        public List QueryNear(string keywords,int pageIndex, int pageSize, double longitude, double latitude, int maxDistance);
    }

MapinfoMongoRepository

public class MapinfoMongoRepository : IMapinfoMongoRepository
    {
        private readonly ILogger _logger;
        private readonly IMongoDbGenericHelper _mapinfoHelper;
        public MapinfoMongoRepository(ILogger logger, IMongoDbGenericHelper mapinfoHelper)
        {
            _logger = logger;
            _mapinfoHelper = mapinfoHelper;
        }

        /// 
        /// 查询附近的信息
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public List QueryNear(string keywords, int pageIndex, int pageSize, double longitude, double latitude, int maxDistance)
        {
   
            IList stages = new List();
            string temp1 = "";
            if (!string.IsNullOrEmpty(keywords))
            {
                temp1 = "{"$geoNear": {"near": {"type": "Point","coordinates": [" + longitude + "," + latitude + "]},"distanceField": "distance","spherical": true,"maxDistance": " + maxDistance + ",query:{"address": { $regex: '" + keywords + "' }}}}";
            }
            else
            {
                temp1 = "{"$geoNear": {"near": {"type": "Point","coordinates": [" + longitude + "," + latitude + "]},"distanceField": "distance","spherical": true,"maxDistance": " + maxDistance + "}}";
            }

            PipelineStageDefinition stage1 = new JsonPipelineStageDefinition(temp1);
            stages.Add(stage1);

            string temp2 = "{$skip:" + (pageIndex - 1) * pageSize + "}";
            PipelineStageDefinition stage2 = new JsonPipelineStageDefinition(temp2);
            stages.Add(stage2);

            string temp3 = "{$limit:" + pageSize + "}";
            PipelineStageDefinition stage3 = new JsonPipelineStageDefinition(temp3);
            stages.Add(stage3);

            PipelineDefinition pipeline = new PipelineStagePipelineDefinition(stages);

            //聚合结果
            List result = _mapinfoHelper.GetCollection(nameof(Models.MongoEnity.mapinfo)).Aggregate(pipeline).ToList();

            return result;
        }
    }

Action

 [HttpGet]
        public IActionResult TestQueryNear()
        {
            var data = _mapinfoMongoRepository.QueryNear(keywords: string.Empty, pageIndex: 1, pageSize: 2, longitude: 119.627438, latitude: 29.078988, maxDistance: 15000);
            return Ok(data);
        }

查询结果:


查询结果

查询结果 distance单位是米

[
  {
    "id": "64ae31fe6412e519c80f4b3d",
    "address": "星月花园",
    "name": "星月花园",
    "distance": 797.0567583679608,
    "location": {
      "Coordinates": {
        "Values": [
          119.635592,
          29.078292
        ],
        "Longitude": 119.635592,
        "Latitude": 29.078292
      },
      "Type": 7,
      "BoundingBox": null,
      "CoordinateReferenceSystem": null,
      "ExtraMembers": null
    }
  },
  {
    "id": "64ae31fe6412e519c80f4b3c",
    "address": "西京大厦",
    "name": "西京大厦",
    "distance": 933.0219480837998,
    "location": {
      "Coordinates": {
        "Values": [
          119.63645,
          29.081855
        ],
        "Longitude": 119.63645,
        "Latitude": 29.081855
      },
      "Type": 7,
      "BoundingBox": null,
      "CoordinateReferenceSystem": null,
      "ExtraMembers": null
    }
  }
]

知识整理不易,喜欢的朋友家个guanzhu呗

展开阅读全文

页面更新:2024-04-07

标签:西京   兰溪   金华市   星月   距离   新世纪   江南   大厦   花园   数据   空间

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top