我有一个索引,用于在嵌套对象中存储一组地理位置。
{
......,
"geo_points" : [
{
"lat" : ...
"lon" : ...
},
.......
]
}
和查询
{
sort: {
_geo_distance: {
geo_points: {
lat: "",
lon: ""
},
order: 'asc',
unit: 'km'
}
},
query: {
filtered: {
query: {
bool: {
must: [
{
range: {
endtime: {gte: ""}
}
},
{
range:{
starttime: {lte: ""}
}
}
],
should: [
{
nested: {
path: 'categories',
filter: {
bool: {
should: { terms: { 'categories.id' => [1,2,3,4]} }
}
}
}
}
],
minimum_number_should_match: 1
}
},
filter: {
geo_distance: {
distance: "25km",
geo_points: {lat: "",lon: ""}
}
}
}
},
from: 0, size: 100
}
它用于地理查询(按距离排序),我想知道是否可以返回只有匹配位置或
的geo_points我可以说只返回X位置吗?
是否有现成的方法inner_hits?而且,如果可能的话,你可以给我一个样本查询吗?
感谢。
答案 0 :(得分:0)
I solved my issue with custom ES script since I couldn't find a proper inbuilt way so here what I did
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.geo.GeoPoint;
/***
*
* usage
* "script_fields": {
* "closest_points": {
* "script": {
* "lang": "groovy",
* "file": "sortedGeoPoints",
* "params": {
* "field": "lokasyonlar",
* "lon": 26.954897,
* "lat": 38.7762021,
* "method": "PLANE",
* "unit": "km",
* "order": "asc",
* "limit": 5
* }
* }
* }
* }
*
*/
if (doc[field].values.size() < limit){
return doc[field]
}
else{
def distanceUnit
def geoCalculator
switch (method){
case "ARC" :
geoCalculator = GeoDistance.ARC
break
case "FACTOR" :
geoCalculator = GeoDistance.FACTOR
break
default:
geoCalculator = GeoDistance.PLANE
break
}
switch (unit) {
case "in" : //inch
distanceUnit = DistanceUnit.INCH
break
case "yd": //yards
distanceUnit = DistanceUnit.YARD
break
case "ft": //feet
distanceUnit = DistanceUnit.FEET
break
case "nmi": //NAUTICALMILES
distanceUnit = DistanceUnit.NAUTICALMILES
break
case "mm": // MILLIMETERS
distanceUnit = DistanceUnit.MILLIMETERS
break
case "cm": // CENTIMETERS
distanceUnit = DistanceUnit.CENTIMETERS
break
case "mi": // MILES
distanceUnit = DistanceUnit.MILES
break
case "m": // MILES
distanceUnit = DistanceUnit.METERS
break
default:
distanceUnit = DistanceUnit.KILOMETERS
break
}
def sortedGeoPoints = new TreeMap<Double, GeoPoint>()
for(i = 0; i < doc[field].values.size(); i++){
def loc = doc[field].values[i]
sortedGeoPoints.put(geoCalculator.calculate(loc.lon, loc.lat, lon, lat, distanceUnit), loc)
}
def list
if(order == "desc"){
list = new ArrayList<GeoPoint>(sortedGeoPoints.descendingMap().values()) //reversed
}
else{
list = new ArrayList<GeoPoint>(sortedGeoPoints.values())
}
return list.subList(0, limit)
}
and sample query
curl -XPOST /geo/test/_search -d '{
"fields": [
"_source",
"distances"
],
"query": {
"bool": {
"must": [
{
"geo_distance": {
"distance": "100km",
"locations": {
"lon": 28.442826999999966,
"lat": 37.101167
}
}
}
]
}
},
"script_fields": {
"closest_points": {
"script": {
"lang": "groovy",
"file": "sortedGeoPoints",
"params": {
"field" : "locations",
"lon": 28.442826999999966,
"lat": 37.101167,
"method" : "PLANE",
"unit" : "km",
"order" : "asc",
"limit" : 3
}
}
}
},
"sort": {
"_geo_distance": {
"locations": {
"lon": 28.442826999999966,
"lat": 37.101167
},
"order": "asc",
"unit": "km"
}
}
}'
Use case & full story can be found in gist
In fact, it can be extracted from _geo_distance sort. However, I don't believe enough to have such functionality at there.
I will keep this open for better inbuilt options if there is, please let us know