2015-04-08 2 views
2

У меня есть класс Java, который выглядит следующим образом (GeoPoint является тип Elasticsearch):Как использовать geo_point с geohash в Elasticsearch с классом Java?

private Long id; 
private Integer genre; 
private String cityName; 
private GeoPoint geoPoint; 
private Date lastUpdate; 
private Double lat; 
private Double lon; 

Отображение Elasticsearch я использую:

{ 
    "location": { 
     "properties": { 
      "id": {"type": "long"}, 
      "genre": {"type": "integer"}, 
      "cityName": {"type": "string"}, 
      "geoPoint": { 
       "type": "geo_point", 
       "geohash": true, 
       "geohash_prefix": true, 
       "geohash_precision": 7 
      }, 
      "lastUpdate": {"type": "date", format: "yyyy/MM/dd HH:mm:ss"} 
     } 
    } 
} 

При попытке проиндексировать его, я получаю следующее исключение:

org.elasticsearch.ElasticsearchParseException: поле должно быть либо широты/долготы или geohash

Исключение составляет от line 381 of the GeoUtils class. Это происходит сразу после проверки полей Double lat и lon в классе сопоставления, как и свойства GeoPoint.

Я не понимаю, почему это не работает, учитывая, что я задал тип поля geoPoint как geo_point, как предлагает ElasticSearch documentation.

UPDATE 1

Класс Java.

public class UserLocation implements Serializable { 

    private Long id; 
    private Integer genre; 
    private String cityName; 
    private GeoPoint geoPoint; 
    private Date lastUpdate; 

    public UserLocation() { 
    } 

    public UserLocation (UserLocationLite userLocationLite) { 

     this.id = userLocationLite.getId(); 
     this.genre = userLocationLite.getGenre(); 
     this.cityName = userLocationLite.getCity(); 
     this.geoPoint = 
       new GeoPoint(userLocationLite.getLatitude(), userLocationLite.getLongitude()); 
     this.lastUpdate = userLocationLite.getActivity(); 
    } 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public Integer getGenre() { 
     return genre; 
    } 

    public void setGenre(Integer genre) { 
     this.genre = genre; 
    } 

    public String getCityName() { 
     return cityName; 
    } 

    public void setCityName(String cityName) { 
     this.cityName = cityName; 
    } 

    public GeoPoint getGeoPoint() { 
     return geoPoint; 
    } 

    public void setGeoPoint(GeoPoint geoPoint) { 
     this.geoPoint = geoPoint; 
    } 

    public Date getLastUpdate() { 
     return lastUpdate; 
    } 

    public void setLastUpdate(Date lastUpdate) { 
     this.lastUpdate = lastUpdate; 
    } 

} 

Способ индексации.

@Override 
public boolean save(String id, R r) { 

    try { 

     return this.transportClient.prepareIndex(this.index, this.type, id) 
       .setSource(this.objectMapper.writeValueAsString(r)) 
       .execute().actionGet().isCreated(); 
    } catch (JsonProcessingException e) { 

     e.printStackTrace(); 
    } 

    return false; 
} 

Где R является один общий тип реализован для другого класса, в данном случае с классом UserLocation, который сериализован следующим образом.

{"id":40,"genre":1,"cityName":"Madrid","geoPoint":{"lat":42.626595,"lon":-0.488439,"geohash":"ezrm5c0vx832"},"lastUpdate":1402144560000} 

UPDATE 2

Прямо сейчас структура класса Java работает отлично.

public class UserLocationSearch implements Serializable { 

    private Long id; 
    private Integer genre; 
    private String cityName; 
    @JsonIgnore 
    private GeoPoint geoPoint; 
    private Date lastUpdate; 

    public UserLocationSearch() { 

     this.geoPoint = new GeoPoint(); 
    } 

    public UserLocationSearch(UserLocationLite userLocationLite) { 

     this.id = userLocationLite.getId(); 
     this.genre = userLocationLite.getGenre(); 
     this.cityName = userLocationLite.getCity(); 
     this.geoPoint = 
       new GeoPoint(userLocationLite.getLatitude(), userLocationLite.getLongitude()); 
     this.lastUpdate = userLocationLite.getActivity(); 
    } 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public Integer getGenre() { 
     return genre; 
    } 

    public void setGenre(Integer genre) { 
     this.genre = genre; 
    } 

    public String getCityName() { 
     return cityName; 
    } 

    public void setCityName(String cityName) { 
     this.cityName = cityName; 
    } 

    public GeoPoint getGeoPoint() { 
     return geoPoint; 
    } 

    public void setGeoPoint(GeoPoint geoPoint) { 
     this.geoPoint = geoPoint; 
    } 

public String getGeohash() { 
    return this.geoPoint.getGeohash(); 
} 

public void setGeohash(String geohash) { 
    this.geoPoint.resetFromGeoHash(geohash); 
} 

public Date getLastUpdate() { 
    return lastUpdate; 
} 

public void setLastUpdate(Date lastUpdate) { 
    this.lastUpdate = lastUpdate; 
} 

}

Но теперь я другой вопрос.

Если получить документ.

GET/пользователь/местоположение/40

{ 
    "_index": "user", 
    "_type": "location", 
    "_id": "40", 
    "_version": 7, 
    "found": true, 
    "_source": { 
     "id": 40, 
     "genre": 1, 
     "cityName": "Madrid", 
     "lastUpdate": 1402144560000, 
     "geohash": "ezrm5c28d9x0" 
    } 
} 

geohash имеет 12 символов, но в отображении geohash точности устанавливается в 7 ...

GET/пользователь/место/_mapping

{ 
    "user": { 
     "mappings": { 
     "location": { 
      "properties": { 
       "cityName": { 
        "type": "string" 
       }, 
       "genre": { 
        "type": "integer" 
       }, 
       "geoPoint": { 
        "type": "geo_point", 
        "geohash": true, 
        "geohash_prefix": true, 
        "geohash_precision": 7 
       }, 
       "geohash": { 
        "type": "string" 
       }, 
       "id": { 
        "type": "long" 
       }, 
       "lastUpdate": { 
        "type": "date", 
        "format": "yyyy/MM/dd HH:mm:ss" 
       } 
      } 
     } 
     } 
    } 
} 

Это означает, что он работает неправильно?

UPDATE 3

Текущий класс.

public class UserLocationSearch implements Serializable { 

    private Long id; 
    private Integer genre; 
    private String cityName; 
    private Location location; 
    private GeoPoint geoPoint; 
    private Date lastUpdate; 

    public UserLocationSearch() { 

    } 

    public UserLocationSearch(UserLocationLite userLocationLite) { 

     this.id = userLocationLite.getId(); 
     this.genre = userLocationLite.getGenre(); 
     this.cityName = userLocationLite.getCity(); 
     this.location = new Location(userLocationLite.getLatitude(), userLocationLite.getLongitude()); 
     this.geoPoint = new GeoPoint(this.location.getGeohash()); 
     this.lastUpdate = userLocationLite.getActivity(); 
    } 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public Integer getGenre() { 
     return genre; 
    } 

    public void setGenre(Integer genre) { 
     this.genre = genre; 
    } 

    public String getCityName() { 
     return cityName; 
    } 

    public void setCityName(String cityName) { 
     this.cityName = cityName; 
    } 

    public Location getLocation() { 
     return location; 
    } 

    public void setLocation(Location location) { 
     this.location = location; 
    } 

    public GeoPoint getGeoPoint() { 
     return geoPoint; 
    } 

    public void setGeoPoint(GeoPoint geoPoint) { 
     this.geoPoint = geoPoint; 
    } 

    public Date getLastUpdate() { 
     return lastUpdate; 
    } 

    public void setLastUpdate(Date lastUpdate) { 
     this.lastUpdate = lastUpdate; 
    } 

    public static class GeoPoint{ 

     private String geohash; 

     public GeoPoint() { 

     } 

     public GeoPoint(String geohash) { 

      this.geohash = geohash; 
     } 

     public String getGeohash() { 
      return geohash; 
     } 

     public void setGeohash(String geohash) { 
      this.geohash = geohash; 
     } 
    } 

    public static class Location{ 

     private Double lat; 
     private Double lon; 

     public Location() { 

     } 

     public Location(Double lat, Double lon) { 

      this.lat = lat; 
      this.lon = lon; 
     } 

     public Double getLat() { 
      return lat; 
     } 

     public void setLat(Double lat) { 
      this.lat = lat; 
     } 

     public Double getLon() { 
      return lon; 
     } 

     public void setLon(Double lon) { 
      this.lon = lon; 
     } 

     @JsonIgnore 
     public String getGeohash(){ 

      return new org.elasticsearch.common.geo.GeoPoint(this.lat, this.lon).getGeohash(); 
     } 

    } 

} 

Его картографирование.

{ 
    "location": { 
     "properties": { 
      "id": {"type": "long"}, 
      "genre": {"type": "integer"}, 
      "cityName": {"type": "string"}, 
      "location": { 
       "type": "geo_point", 
       "geohash": false 
      }, 
      "geoPoint": { 
       "type": "geo_point", 
       "geohash": true, 
       "geohash_prefix": true, 
       "geohash_precision": 7 
      }, 
      "lastUpdate": {"type": "date", format: "yyyy/MM/dd HH:mm:ss"} 
     } 
    } 
} 

Поиск.

По расстоянию (отлично работает).

GET/пользователь/местоположение/_search

{ 
    "query": { 
    "match_all": {} 
    }, 
    "filter": { 
    "geo_distance": { 
     "distance": "100km", 
     "location": { 
     "lat": 42.5, 
     "lon": -0.49 
     } 
    } 
    } 
} 

По geohash (работает тоже хорошо, более 7 точности игнорируется, поскольку он отображается с "geohash_precision: 7").

GET/пользователь/местоположение/_search

{ 
    "query": { 
    "filtered": { 
     "filter": { 
     "geohash_cell": { 
      "geoPoint": { 
      "geohash": "ezrm5c0y5rh8" 
      }, 
      "neighbors": true, 
      "precision": 7 
     } 
     } 
    } 
    } 
} 

ЗАКЛЮЧЕНИЕ

Я не понимаю, почему класс причина org.elasticsearch.common.geo.GeoHashUtils.GeoPoint не совместим с фактическим Упругая версия.

Но, следуя трекам, предоставленным @jkbkot, я решил реализовать свои собственные классы GeoPoint и Location, чтобы получить полную совместимость.

+0

Непонятно, что вы пытаетесь проиндексировать. Можете ли вы показать пример документа? Или у вас есть JavaBean, который вы трансформируете в JSON? –

+0

, что нам нужно, чтобы помочь вам, либо является исходным кодом для 'R', либо, может быть, даже лучшим выходом, например:' System.out.println (this.objectMapper.writeValueAsString (r)) ' –

+0

Извините jkbkot, вчера я ответил на ваш вопрос снизу, но не видел этого комментария. Я обновляю основной вопрос с помощью сериализации R (экземпляр UserLocation). – Dani

ответ

2

Следующая Sense script должно дать вам представление о том, что делать:

DELETE location 
PUT location 
PUT location/location/_mapping 
{ 
"location": { 
    "properties": { 
     "id": {"type": "long"}, 
     "genre": {"type": "integer"}, 
     "cityName": {"type": "string"}, 
     "geoPoint": { 
      "type": "geo_point", 
      "geohash": true, 
      "geohash_prefix": true, 
      "geohash_precision": 7 
     }, 
     "lastUpdate": {"type": "date", format: "yyyy/MM/dd HH:mm:ss"} 
    } 
} 
} 
GET location/location/_mapping 

PUT location/location/1 
{"id":40,"genre":1,"cityName":"Madrid","geoPoint":{"geohash":"ezrm5c0vx832"},"lastUpdate":1402144560000} 

GET /location/location/_search 
{ 
    "query" : { 
     "match_all": {} 
    }, 
    "filter" : { 
     "geo_distance" : { 
      "distance" : "40km", 
      "geoPoint" : { 
       "lat" : 42.5, 
       "lon" : -0.49 
      } 
     } 
    } 
} 

Вы должны преобразовать класс Java, который держит документ в формате JSON со структурой, как либо:

{ 
    "id": 40, 
    "genre": 1, 
    "cityName": "Madrid", 
    "geoPoint": { 
     "geohash": "ezrm5c0vx832" 
    }, 
    "lastUpdate": 1402144560000 
} 

или

{ 
    "id": 40, 
    "genre": 1, 
    "cityName": "Madrid", 
    "geoPoint": { 
     "lat": 42.626595, 
     "lon": -0.488439 
    }, 
    "lastUpdate": 1402144560000 
} 

Так что либо вы должны удалить, например, private GeoPoint geoPoint; из вашего класса Java и оставьте lat и lon там (или наоборот), или вам нужно изменить, как вы сериализуете класс в строку JSON, - чтобы опустить либо geoPoint, либо оба lat и lon.

+0

Ty jkbkot, я обновил вопрос. – Dani

+0

Ty снова jkbkot, но теперь у меня есть другой вопрос, обновленный в # 1. – Dani

+1

Исправить это, ty jkbkot. :) – Dani

Смежные вопросы