본문 바로가기

Elasticsearch

Elasticsearch geographic location query distance 거리로 가까운 곳 검색하기

반응형

 

1. Elasticsearch 의 GEO DATA TYPE 

1) geo_point

Logitude 경도, Latitude 위도를 사용하는 geo_point는 radius (반경) 내의 특정 범위 내를 검색할 수 있다. "point" 어느 지점을 딱 포인트한다 라고 이해했다 .

 

2) geo_shape

geo_shape은 GeoJson을 사용하여 복잡한 그래프를 나타낸다. 만약 거~ 대한 박물관이 존재한다면 해당 박물관의 좌표는 한 "point"에서 끝나지않고 큰 범위를 이룰 것이다. 이 때 사용하는 것이 geo_shape 이다. 

 

 

 

2. Elsaticsearch Geo_point search 검색 사용 방법 

filter에 geo_distance를 걸어준다. 

            filter: {
              geo_distance: {
                distance: 1km,
                location: [126.123123, 35.121312]
              },
            },

geo_distance와 그 안의 객체 distance는 정해져 있는 프로퍼티이고 location은 내가 찾을 인덱스의 mapping proprerties 중 좌표를 담는 field 이름을 적으면 된다. 

 

 

 

예를 들어

아래와 같이 Mapping한 index "testda" 에서 geo_distance를 적용한다고 한다면 



1. geo_point를 사용할 인덱스 생성 

PUT testda
{
  "mappings": {
    "properties": {
      "locationYiDa": {
        "type": "geo_point"
      }
    }
  }
}

testda 인덱스에 "locationYiDa"라는 필드를 mapping했다. LocationYiDa의 타입은 geo_point로 위에서 설명한 어느 한 포인트를 찝는 좌표값을 넣을 수 있다. 좌표 데이터를 입력하는 방식은 6가지가 있다. 

 

 

2. 6가지 방식 중 원하는 것으로 데이터 입력

PUT testDa/_doc/1
{
  "text": "Geopoint as an object using GeoJSON format",
  "locationYiDa": { 
    "type": "Point",
    "coordinates": [-71.34, 41.12]
  }
}

PUT testDa/_doc/2
{
  "text": "Geopoint as a WKT POINT primitive",
  "locationYiDa" : "POINT (-71.34 41.12)" 
}

PUT testDa/_doc/3
{
  "text": "Geopoint as an object with 'lat' and 'lon' keys",
  "locationYiDa": { 
    "lat": 41.12,        // 이 경우 lat (위도) 가 먼저 온다. *** 위치 조심해야함 
    "lon": -71.34
  }
}

PUT testDa/_doc/4
{
  "text": "Geopoint as an array",
  "locationYiDa": [ -71.34, 41.12 ] 
}

PUT testDa/_doc/5
{
  "text": "Geopoint as a string",
  "locationYiDa": "41.12,-71.34" 
}

PUT testDa/_doc/6
{
  "text": "Geopoint as a geohash",
  "locationYiDa": "drm3btev3e86" 
}

 

나는 위 방식 중 첫 번째로 데이터를 저장했다. 

 

3. 특정 좌표 반경 내에 있는 데이터 조회하기

    const result = await client.search({
      _source: ['idx', 'location']    //원하는 field만 반환하기 
      index: 'testDa',
      size: 20,      // 반환 도큐먼트 개수
      body: {
        min_score: 1,  // 반환되기위한 도큐먼트 스코어 최소 점수
        query: {
          bool: {
            must: {
              match_all: {},
            },
            filter: {
              geo_distance: {
                distance: 1km,   // 반경 - 반경 단위는 아래에 첨부
                location: [127.123123, 35.123123], // point 중심이 될 좌표 
                distance_type: 'arc', // arc가 default
              },
            },
          },
        },
      },
    });
    
    console.log('result =', result.body.hits.hits);

location 필드 중 위의 입력된 127.123123, 35.123123 좌표값을 중심으로 반경 1km 이내의 값이 검색된다. 

distance_type은 arc가 디폴트이고 plain 값도 있다. plain은 더 빠르지만 장거리일수록, 극지방에 가까울수록 부정확하다. 

 

 

 

distance에 사용할 수 있는 단위는 아래와 같다. 

km, m, cm, mm, nmi, mi, yd, ft, in 

 

 

 

 

Reference : https://developpaper.com/elasticsearch-geographic-location-query/

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-distance-query.html

 

반응형