C#用弹性搜索计算地理距离(nest 2)
C# calculate geodistance with elastic search (nest 2)
我正在实现一个能够接收 10 个最近对象的程序。作为数据库,我使用 ElasticSearch,我的模型如下所示。
[Nest.ElasticsearchType(Name = "eventelastic", IdProperty = "Id")]
public class EventElastic:BaseElastic
{
[Nest.String]
public string EventName { get; set; }
[Nest.Date]
public DateTime CreateTime { get; set; }
[Nest.String]
public string Country { get; set; }
[Nest.String]
public string City { get; set; }
[Nest.String]
public string Place { get; set; }
[Nest.Boolean]
public bool IsPrivate { get; set; }
[Nest.Boolean]
public bool IsSponsored { get; set; }
[Nest.String]
public string ImageWeb { get; set; }
[Nest.Number]
public int MaxPersons { get; set; }
[Nest.GeoPoint]
public LocationModel Location { get; set; }
}
[Nest.ElasticsearchType(Name = "location", IdProperty = "Id")]
public class LocationModel
{
public LocationModel(double lon, double lat)
{
Lon = lon;
Lat = lat;
}
public double Lon { get; set; }
public double Lat { get; set; }
}
我创建了一个这样的索引
connection.CreateIndex("index", s => s.Mappings(f => f.Map<EventElastic>(m => m.AutoMap().Properties(p=> p.GeoPoint(g => g.Name(n => n.Location))))));
然后我像这样插入新文档
var response = connection.IndexAsync<EventElastic>(model, idx => idx.Index("index"));
response.ContinueWith(t =>
{
if (!t.Result.IsValid)
{
log.Error(t.Result.ServerError.Error.Reason);
}
});
模型的所有值都已设置,并且可以正常工作。
但现在我想在 10 公里范围内获取最近的 10 个。
我这样查询
var geoResult = connection.Search<EventElastic>(s => s.From(0).Size(10)
.Query(query => query.Bool(b => b.Filter(filter => filter
.GeoDistance(geo => geo
.Field(f => f.Location) //<- this
.Distance("10km").Location(lon, lat)
.DistanceType(GeoDistanceType.SloppyArc)
))
)
)
);
但它没有 return 任何文档,但如果我将距离值设置为 10000km,它 return 是一个文档。
我在模型中使用的数据是:
拉特:47.4595248
经度:9.6385962
我在搜索中使用的位置:
拉特:47.4640298
伦敦:9.6389685
那些地方相距100米。
有人可以帮我找出代码中的错误吗?
是否可以从elasticsearch服务器获取计算的距离?
顺便说一句:我正在设置默认索引
var settings = new ConnectionSettings(pool).DefaultIndex("index");
编辑
我发现了错误:
var geoResult = connection.Search<EventElastic>(s => s.From(0).Size(10)
.Query(query => query.Bool(b => b.Filter(filter => filter
.GeoDistance(geo => geo
.Field(f => f.Location)
.Distance("10km").Location(lat, lon) //wrong parameter
.DistanceType(GeoDistanceType.SloppyArc)
))
)
)
);
我不得不改变纬度和经度的位置。
但是我没有得到计算的距离,有人知道我怎样才能得到距离吗?
此致
您可以将 Distance
添加到您的文档中,并在您的查询中使用 sctipt fields 来更新此值。
var geoResult = client.Search<EventElastic>(s => s.From(0).Size(10)
.ScriptFields(sf => sf
.ScriptField("distance", descriptor => descriptor
.Inline("doc[\u0027location\u0027].distanceInKm(lat,lon)")
.Lang("groovy")
.Params(f => f.Add("lat", lat).Add("lon", lon))))
.Query(query => query.Bool(b => b.Filter(filter => filter
.GeoDistance(geo => geo
.Field(f => f.Location)
.Distance("10km").Location(lat, lon)
.DistanceType(GeoDistanceType.SloppyArc)
))
)
)
.Sort(sort => sort
.GeoDistance(g => g
.Field(f => f.Location)
.Order(SortOrder.Ascending)
.PinTo(new GeoLocation(1.5, 1))
.DistanceType(GeoDistanceType.SloppyArc)))
);
public class EventElastic
{
..
public double Distance {get;set;}
}
elasticsearch 的响应:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": null,
"hits": [
{
"_index": "my_index",
"_type": "data",
"_id": "1",
"_score": null,
"fields": {
"distance": [
55.65975203179589
]
},
"sort": [
55659.66677843493
]
},
{
"_index": "my_index",
"_type": "data",
"_id": "2",
"_score": null,
"fields": {
"distance": [
124.45896068602408
]
},
"sort": [
124411.81715215484
]
}
]
}
}
希望对您有所帮助。
我正在实现一个能够接收 10 个最近对象的程序。作为数据库,我使用 ElasticSearch,我的模型如下所示。
[Nest.ElasticsearchType(Name = "eventelastic", IdProperty = "Id")]
public class EventElastic:BaseElastic
{
[Nest.String]
public string EventName { get; set; }
[Nest.Date]
public DateTime CreateTime { get; set; }
[Nest.String]
public string Country { get; set; }
[Nest.String]
public string City { get; set; }
[Nest.String]
public string Place { get; set; }
[Nest.Boolean]
public bool IsPrivate { get; set; }
[Nest.Boolean]
public bool IsSponsored { get; set; }
[Nest.String]
public string ImageWeb { get; set; }
[Nest.Number]
public int MaxPersons { get; set; }
[Nest.GeoPoint]
public LocationModel Location { get; set; }
}
[Nest.ElasticsearchType(Name = "location", IdProperty = "Id")]
public class LocationModel
{
public LocationModel(double lon, double lat)
{
Lon = lon;
Lat = lat;
}
public double Lon { get; set; }
public double Lat { get; set; }
}
我创建了一个这样的索引
connection.CreateIndex("index", s => s.Mappings(f => f.Map<EventElastic>(m => m.AutoMap().Properties(p=> p.GeoPoint(g => g.Name(n => n.Location))))));
然后我像这样插入新文档
var response = connection.IndexAsync<EventElastic>(model, idx => idx.Index("index"));
response.ContinueWith(t =>
{
if (!t.Result.IsValid)
{
log.Error(t.Result.ServerError.Error.Reason);
}
});
模型的所有值都已设置,并且可以正常工作。
但现在我想在 10 公里范围内获取最近的 10 个。 我这样查询
var geoResult = connection.Search<EventElastic>(s => s.From(0).Size(10)
.Query(query => query.Bool(b => b.Filter(filter => filter
.GeoDistance(geo => geo
.Field(f => f.Location) //<- this
.Distance("10km").Location(lon, lat)
.DistanceType(GeoDistanceType.SloppyArc)
))
)
)
);
但它没有 return 任何文档,但如果我将距离值设置为 10000km,它 return 是一个文档。
我在模型中使用的数据是: 拉特:47.4595248 经度:9.6385962
我在搜索中使用的位置: 拉特:47.4640298 伦敦:9.6389685
那些地方相距100米。 有人可以帮我找出代码中的错误吗? 是否可以从elasticsearch服务器获取计算的距离?
顺便说一句:我正在设置默认索引
var settings = new ConnectionSettings(pool).DefaultIndex("index");
编辑 我发现了错误:
var geoResult = connection.Search<EventElastic>(s => s.From(0).Size(10)
.Query(query => query.Bool(b => b.Filter(filter => filter
.GeoDistance(geo => geo
.Field(f => f.Location)
.Distance("10km").Location(lat, lon) //wrong parameter
.DistanceType(GeoDistanceType.SloppyArc)
))
)
)
);
我不得不改变纬度和经度的位置。
但是我没有得到计算的距离,有人知道我怎样才能得到距离吗?
此致
您可以将 Distance
添加到您的文档中,并在您的查询中使用 sctipt fields 来更新此值。
var geoResult = client.Search<EventElastic>(s => s.From(0).Size(10)
.ScriptFields(sf => sf
.ScriptField("distance", descriptor => descriptor
.Inline("doc[\u0027location\u0027].distanceInKm(lat,lon)")
.Lang("groovy")
.Params(f => f.Add("lat", lat).Add("lon", lon))))
.Query(query => query.Bool(b => b.Filter(filter => filter
.GeoDistance(geo => geo
.Field(f => f.Location)
.Distance("10km").Location(lat, lon)
.DistanceType(GeoDistanceType.SloppyArc)
))
)
)
.Sort(sort => sort
.GeoDistance(g => g
.Field(f => f.Location)
.Order(SortOrder.Ascending)
.PinTo(new GeoLocation(1.5, 1))
.DistanceType(GeoDistanceType.SloppyArc)))
);
public class EventElastic
{
..
public double Distance {get;set;}
}
elasticsearch 的响应:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": null,
"hits": [
{
"_index": "my_index",
"_type": "data",
"_id": "1",
"_score": null,
"fields": {
"distance": [
55.65975203179589
]
},
"sort": [
55659.66677843493
]
},
{
"_index": "my_index",
"_type": "data",
"_id": "2",
"_score": null,
"fields": {
"distance": [
124.45896068602408
]
},
"sort": [
124411.81715215484
]
}
]
}
}
希望对您有所帮助。