/// <summary> /// 附近的人,最多返回100个 /// </summary> /// <param name="lat">维度</param> /// <param name="lng">经度</param> /// <param name="radius">半径,单位为米,当radius为零时表示使用默认初始范围,并自动扩大范围, 每次扩大20km,最大到500km</param> private IEnumerable <GeoRadiusResult> NearbyUsers(double lat, double lng, double radius, ref PageViewModel page, Func <int[], int[]> filterUser = null, string key = RedisConfigureDbModel.GEODbModel) { var needExt = radius == 0; //是否需要自动扩展 Stopwatch watch = new Stopwatch(); watch.Start(); var extStep = 100000; var extMax = 20000000; if (radius == 0) { radius = extStep; } page = page ?? PageViewModel.Default(); var db = getRedis().GetDatabase((int)RedisDbIndex.GEO); var pos = new GeoPosition(lng, lat); GeoRadius geoRadius; List <GeoRadiusResult> finalResult = new List <GeoRadiusResult>(); var extTimes = 0; var preCount = 0;//记录上次查询到的数量,, 再过滤时跳过 while (extTimes == 0 || (needExt && !page.CurrentPageIsFull && radius < extMax)) { geoRadius = new GeoRadius( key, pos, radius, 20000000, GeoUnit.Meters, DTO.GeoRadiusOptions.WithCoordinates | DTO.GeoRadiusOptions.WithDistance ); var result = db.GeoRadius(key, geoRadius.GeoPosition.Longitude, geoRadius.GeoPosition.Latitude, radius); if (result.Count() > preCount) //有新id拿到才需要过滤 { var newResult = result.Skip(preCount).ToArray(); var newUserIds = newResult.Select(e => Int32.Parse(e.Member)).ToArray(); //找出新查询到的UserId, if (filterUser != null)//Remove excluded { newUserIds = filterUser(newUserIds).ToArray(); } finalResult.AddRange(newResult.Where(e => newUserIds.Contains(Int32.Parse(e.Member)))); } preCount = result.Count(); extTimes++; radius += extStep; page.RecordCount = finalResult.Count(); } //处理最后页一条正好满的情况. 再增加一页 if (page.CurrentPageIsFull && page.PageNo == page.PageCount) { page.RecordCount += 1; } watch.Stop(); return(finalResult.Skip(page.Skip).Take(page.PageSize)); }