사전 주의사항
FT.SEARCH 를 사용하기 위해서는 RedisSearch Module이 사전에 설치되어있어야 가능합니다.
Redis에서는 RedisStack을 이용하는 방법을 추천하고 있습니다.
별도 설치 혹은 Redis Cloud를 사용하는 방법이 있습니다.
별도 설치 중 Docker를 이용하여 설치하는 방법은 제가 작성한 블로그를 참고 하셔도 좋습니다.
Data Insert
Index설정과 데이터 조회를 하기 전 지리정보 데이터를 갖진 데이터를 작성합니다.
위도 값은 20으로 고정한채 경도값을 약 1km 너비로 하여 데이터를 생성 했습니다.
HSET geo_table:1 geo "126.0,20" geo_shape "POINT(126.0 20)"
HSET geo_table:2 geo "126.0113,20" geo_shape "POINT(126.0113 20)"
HSET geo_table:3 geo "126.0225,20" geo_shape "POINT(126.0225 20)"
HSET geo_table:4 geo "126.0338,20" geo_shape "POINT(126.0338 20)"
HSET geo_table:5 geo "126.0451,20" geo_shape "POINT(126.0451 20)"
HSET geo_table:6 geo "126.0563,20" geo_shape "POINT(126.0563 20)"
HSET geo_table:7 geo "126.0676,20" geo_shape "POINT(126.0676 20)"
HSET geo_table:8 geo "126.0789,20" geo_shape "POINT(126.0789 20)"
HSET geo_table:9 geo "126.0902,20" geo_shape "POINT(126.0902 20)"
HSET geo_table:10 geo "126.1014,20" geo_shape "POINT(126.1014 20)"
HSET geo_table:11 geo "126.1127,20" geo_shape "POINT(126.1127 20)"
HSET geo_table:12 geo "126.1239,20" geo_shape "POINT(126.1239 20)"
HSET geo_table:13 geo "126.1352,20" geo_shape "POINT(126.1352 20)"
HSET geo_table:14 geo "126.1465,20" geo_shape "POINT(126.1465 20)"
HSET geo_table:15 geo "126.1578,20" geo_shape "POINT(126.1578 20)"
HSET geo_table:16 geo "126.1690,20" geo_shape "POINT(126.1690 20)"
HSET geo_table:17 geo "126.1803,20" geo_shape "POINT(126.1803 20)"
HSET geo_table:18 geo "126.1916,20" geo_shape "POINT(126.1916 20)"
HSET geo_table:19 geo "126.2028,20" geo_shape "POINT(126.2028 20)"
HSET geo_table:20 geo "126.2141,20" geo_shape "POINT(126.2141 20)"
해당 위도 경도 값을 openlayer를 통해 표시 할 경우 다음과 같이 표시 됩니다.

const coordinates = [[126.0, 20],[126.0113, 20],[126.0225, 20],[126.0338, 20],[126.0451, 20],[126.0563, 20],[126.0676, 20],[126.0789, 20],[126.0902, 20],[126.1014, 20],[126.1127, 20],[126.1239, 20],[126.1352, 20],[126.1465, 20],[126.1578, 20],[126.169, 20],[126.1803, 20],[126.1916, 20],[126.2028, 20],[126.2141, 20]];
const features: Feature<Point>[] = [];
coordinates.forEach((cod) => {
const coordinate = fromLonLat([cod[0], cod[1]]);
const point = new Point(coordinate);
const feature = new Feature(point);
features.push(feature);
});
const vectorSource = new VectorSource({
features: features,
});
const pointsLayer = new VectorLayer({
source: vectorSource,
});
baseMap.addLayer(pointsLayer);
Indexing
인덱스는 FT.CREATE 를 통해 생성이 가능합니다. Redis 에서는 다음과 같이 Syntax를 정의 했습니다.
해당 글에서는 ON HASH 형태의 데이터를 인덱싱 할 예정입니다. 이에 JSON 형태의 인덱싱 기법은 링크(JSON Indexing)에 가서 보다 자세히 확인해주시길 바랍니다.
FT.CREATE index [ON HASH | JSON] [PREFIX count prefix [prefix ...]] [FILTER {filter}] [LANGUAGE default_lang] [LANGUAGE_FIELD lang_attribute] [SCORE default_score] [SCORE_FIELD score_attribute] [PAYLOAD_FIELD payload_attribute] [MAXTEXTFIELDS] [TEMPORARY seconds] [NOOFFSETS] [NOHL] [NOFIELDS] [NOFREQS] [STOPWORDS count [stopword ...]] [SKIPINITIALSCAN] SCHEMA field_name [AS alias] TEXT | TAG | NUMERIC | GEO | VECTOR | GEOSHAPE [ SORTABLE [UNF]] [NOINDEX] [ field_name [AS alias] TEXT | TAG | NUMERIC | GEO | VECTOR | GEOSHAPE [ SORTABLE [UNF]] [NOINDEX] ...]
지리 정보 데이터를 조회 하기 위해서는 다음과 같은 필드 타입으로 작성해야 합니다.
- GEO
- Radius 검색 기능을 지원합니다.
- 속성 값은 쉼표로 구분된 경도, 위도를 포함하는 문자열이어야 합니다.
FT.CREATE idx:geo ON HASH PREFIX 1 "geo_table:" SCHEMA geo GEO
- GEOSHAPE
- Radius와 다각형(Polygon) 검색 기능을 지원합니다.
- 속성 값은 쉼표로 구분된 다각형 가장자리를 나타내는 2D 점의 WTK 표기법 목록을 따라야 합니다.
- WKT 표기법 : POLYGON((x1 y1, x2 y2, x3 y3 ... ))
- 좌표계는 SPHERICAL, FLAT 가 존재합니다.
- SPHERICAL : 지리적 경도 및 위도의 좌표계
- FLAT : 데카르트 XY 좌표계
FT.CREATE idx:geoshape ON HASH PREFIX 1 "geo_table:" SCHEMA geo_shape GEOSHAPE SPHERICAL
작성한 인덱스를 삭제하는 방법은 다음과 같다.
FT.DROPINDEX index [DD]
Radius Search
좌표(경도, 위도)를 중심으로 원형 형태로 데이터를 검색할 수 있습니다.
FT.SEARCH index "@geo_field:[lon lat radius unit]"
- lon : 경도
- lat : 위도
- radius : 반지름
- unit : 반지름의 단위 [ m, km, mi, ft ]
현재 작성된 데이터와 인덱스 기반으로 검색 쿼리를 다음과 같이 작성 할 수 있습니다.
FT.SEARCH idx:geo "@geo:[126 20 10 km]"
Shape Search
Shape Search Syntax는 다음과 같습니다.
FT.SEARCH index "@geo_shape_field:[{WITHIN|CONTAINS} $shape] PARAMS 2 shape "shape_as_wkt" DIALECT 3
- @geo_shape_field : 인덱싱으로 선택된 필드 중 질의할 필드명
- WITHIN | CONTAINS
- WITHIN : 지정된 형태 내부에 있는 데이터를 질의
- CONTAINS : 지정된 형태가 포함하는 데이터를 질의
- PARAMS : 쿼리에 사용될 매개 변수의 수와 값을 정의
- DIALECT : 사용할 쿼리 언어의 버전을 지정 DIALECT 3 은 RedisSearch의 쿼리 언어 버전 3을 사용함을 나타냅니다.
검색 쿼리를 다음과 같이 질의를 했습니다.
FT.SEARCH idx:geoshape "@geo_shape:[within $poly]" PARAMS 2 poly "POLYGON((126.1 19.99, 126.1 20.01, 126.2 20.01, 126.2 19.99, 126.1 19.99))" DIALECT 3
총 9개의 데이터가 출력이 되었으며, 10 ~ 18번까지의 데이터가 출력 됨을 확인 할 수 있습니다.
질의한 범위는 openlayer를 통해 표시 할 경우 다음과 같이 표시 됩니다.

const polygonCoordinates = [[126.1, 19.99],[126.1, 20.01],[126.2, 20.01],[126.2, 19.99],[126.1, 19.99]];
const polygon = new Polygon([
polygonCoordinates.map((coord) => fromLonLat(coord)),
]);
const polygonFeature = new Feature(polygon);
const polygonVecotrSource = new VectorSource({
features: [polygonFeature],
});
const polygonLayer = new VectorLayer({ source: polygonVecotrSource });
baseMap.addLayer(polygonLayer);
'Redis' 카테고리의 다른 글
[ Redis ] RedisStack With.Docker (0) | 2024.04.16 |
---|