Java - Elasticsearch:基于距离排序

时间:2015-06-06 05:18:47

标签: elasticsearch

这是我的ES映射

{
  "titan": {
    "mappings": {
      "tagLabelIndices": {
        "_ttl": {
          "enabled": true
        },
        "properties": {
          "tagLabel": {
            "type": "string"
          }
        }
      },
      "objIndices": {
        "_ttl": {
          "enabled": true
        },
        "properties": {
          "objAddress": {
            "type": "string"
          },
          "objGeoLocation": {
            "type": "geo_point"
          },
          "objTitle": {
            "type": "string"
          }
        }
      }
    }
  }
}

现在我想做基于距离的搜索

public static String getTitleBasedQuery( String titleString)
{
    StringBuilder sb = new StringBuilder();
    sb.append(AppConstants.Common.property.objTitle);
    sb.append(":");
    sb.append(titleString);

    return sb.toString();
}

public static ArrayList<Long> esQueryExecuter(Client client,String query, int start, String sortOnField,int resultPerPage,String types,SortOrder order)
{
    SearchResponse response = client.prepareSearch("titan")
    .setTypes(types)
    .setQuery(QueryBuilders.queryString(query))
    .setFrom((start-1)*resultPerPage).setSize(resultPerPage)
    .addSort(sortOnField, order)
    .execute()
    .actionGet();

    SearchHit[] results = response.getHits().getHits();
    ArrayList<Long> al = new ArrayList<Long>();
    for (SearchHit hit : results) 
        al.add(LongEncoding.decode(hit.getId()));
    return al;
}     


System.out.println(esQueryExecuter(esClient, getTitleBasedQuery("Matrix's rain javascript"), 1, AppConstants.Common.property.objGeoLocation.toString(), 10, "objIndices", SortOrder.ASC));

我收到了这个错误:

nested: ElasticsearchIllegalArgumentException[can't sort on geo_point field without using specific sorting feature, like geo_distance]; }

我看到setFilter(GeoDistanceRangeFilterBuilder)的某处,但找不到此方法

1 个答案:

答案 0 :(得分:1)

按距离排序需要一个名为_geo_distance的特定距离排序结构,您可以这样构建

SearchResponse response = client.prepareSearch("titan")
    .setTypes(types)
    .setQuery(QueryBuilders.queryString(query))
    .setFrom((start-1)*resultPerPage).setSize(resultPerPage)
    .addSort(SortBuilders.geoDistanceSort(sortOnField)
        .order(order)
        .point(ORIGIN_LAT, ORIGIN_LON)
        .unit("km"))
    .execute()
    .actionGet();

请注意,您还需要输入ORIGIN_LAT + ORIGIN_LON作为参考点,从中计算要排序的距离。

如果您需要添加搜索范围,可以使用geo_distance filter

GeoDistanceFilterBuilder geoDistanceFilterBuilder = FilterBuilders.geoDistanceFilter(sortOnField)
  .point(ORIGIN_LAT, ORIGIN_LON)
  .distance(10, "km")
  .optimizeBbox("memory")
  .geoDistance(GeoDistance.ARC);

SearchResponse response = client.prepareSearch("titan")
    .setTypes(types)        
    .setQuery(QueryBuilders.filteredQuery(QueryBuilders.queryString(query),
         geoDistanceFilterBuilder))
    .setFrom((start-1)*resultPerPage).setSize(resultPerPage)
    .addSort(SortBuilders.geoDistanceSort(sortOnField)
        .order(order)
        .point(ORIGIN_LAT, ORIGIN_LON)
        .unit("km"))
    .execute()
    .actionGet();