基于Elasticsearch进行地理检索,计算距离值

 

实现步骤:
1、定义属性
    [Serializable]
    public class Coordinate
    {
        public double Lat { get; set; }
 
        public double Lon { get; set; }
    }
 
        /// <summary>
        /// 位置坐标
        /// </summary>
        [ElasticProperty(Type = FieldType.GeoPoint)]
        public Coordinate location { get; set; }
 
        /// <summary>
        /// 返回字段,距离值,适用于地理位置检索和排序  2016-03-25
        /// </summary>
        public double distance { get; set; }
 

 
2、创建索引时,设置Mapping:
_clientES.CreateIndex(indexName, s => s.AddMapping<DTOCarInfoIndexField>(f => f .MapFromAttributes().Properties(p => p.GeoPoint(g => g.Name(n => n.location).IndexLatLon()).String(fullinfo => fullinfo.Name(n => n.fullinfo).Index(FieldIndexOption.Analyzed).Analyzer("ik").Store(false)).String(description => description.Name(n => n.statedescription).Index(FieldIndexOption.Analyzed).Analyzer("ik").Store(false))).AllField(af => af.Enabled(false))).NumberOfReplicas(0));
 

 
3、向ES写入数据时,给location属性赋值:
 
#region 车源坐标  2015-11-30
 
string[] arrValue = ConvertHelper.ToStringArray(value.ToString(), ',');
if (arrValue.Length == 2)
{
    var point = new Coordinate();
    point.Lat = 0.0;
    point.Lon = 0.0;
    double x = ConvertHelper.ToDouble(arrValue[0]);
    double y = ConvertHelper.ToDouble(arrValue[1]);
    if (x > 0 && y > 0)
    {
        point.Lat = x;
        point.Lon = y;
    }
    prop.SetValue(obj, point, null);
}
 
#endregion
 

 
4、搜索过程中按照距离排序并返回距离值(单位:km)(Nest组件):
//构建排序对象
List<KeyValuePair<PropertyPathMarker, ISort>> oneSortList = new List<KeyValuePair<PropertyPathMarker, ISort>>();
SortOrder ordertype = SortOrder.Ascending;
GeoDistanceSort sort = new GeoDistanceSort();
sort.Field = "location";
sort.Order = ordertype;
sort.GeoUnit = GeoUnit.Kilometers;
sort.PinLocation = locationpoint;
oneSortList.Add(new KeyValuePair<PropertyPathMarker, ISort>("_geo_distance", sort));
 
//构建ES检索对象
string[] returnFields=new[]{"id","distance"};
var searchRequest = new SearchRequest();
searchRequest.From = 0;
searchRequest.Size = 20;
searchRequest.Sort = oneSortList;
 
//定义返回列属性
searchRequest.Fields = returnFields.Select(f => (PropertyPathMarker)f.ToLower()).ToList();
 
//添加其他检索条件
//searchRequest.Query = queryList[i];
//searchRequest.Filter = listFilter[i];
 
 
#region 地理检索,添加距离返回值字段
 
if (!string.IsNullOrEmpty(locationPoint) && returnFields.Contains("distance"))
{
    var distancefield = new Dictionary<string, IScriptFilter>();
    var tempfield = new ScriptFilter();
    tempfield.Params = new Dictionary<string, object>();
    tempfield.Params.Add("lat", 116.403951);
    tempfield.Params.Add("lon", 39.915031);
    tempfield.Script = "doc['location'].arcDistanceInKm(lat,lon)";
    distancefield.Add("distance", tempfield);
    searchRequest.ScriptFields = distancefield;
}
 
#endregion
 
//执行检索,获取返回值
var resultSearch = esClient.Search<T>(searchRequest);
foreach (var doc in sResponse.FieldSelections)
{
    var id = doc.FieldValues<object[]>("id").ToList()[0];
    var distancevalue = doc.FieldValues<object[]>("distance").ToList()[0]; 
}
 
 
5、搜索过程中按照距离排序并返回距离值(单位:km)(Linq方式)
ESClient.Instance_TaocheCar().GetElasticClient().Search<DTOCarInfoIndexField>(s => s.From(0).Size(200).Fields(arrField).Filter(filter => filter.Terms("userid", list)).ScriptFields(sf => sf.Add("distance", descriptor => descriptor.Params(p => p.Add("lat", lat).Add("lon", lon)).Script("doc['location'].arcDistanceInKm(lat,lon)"))).SortGeoDistance(sg => sg.OnField("location").PinTo(lat, lon).Unit(GeoUnit.Kilometers).Ascending()));

转载于:https://www.cnblogs.com/lijunhao/p/5341297.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值