티스토리 뷰

ElasticSearch

검색 API

따강아지 2023. 8. 29. 19:46

1. ElasticSearch Analyzer & Mapping 

1-1. analyzer

ElasticSearch( 이하 es ) 의 기본 분석기는 Standard analzer로  공백을 기준으로 문자열을 n개의 토근으로 분리합니다. 추가 해서 필터를 설정 하면 영어인 경우 소문자/대문자로 치환이 가능 합니다. 필터를 하지 않은 Standard analzer를 본다면 ..

curl --location --request GET 'https://172.19.164.132:9200/_analyze?pretty=true' \
--header 'Content-Type: application/json' \ 
--data '{
    "analyzer": "standard",
    "text": "elasticsearch spring-data  한글 nori"
}'
결과 :

=================================================================================
{
    "tokens": [
        {
            "token": "elasticsearch",
            "start_offset": 0,
            "end_offset": 13,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "spring",
            "start_offset": 14,
            "end_offset": 20,
            "type": "<ALPHANUM>",
            "position": 1
        },
        {
            "token": "data",
            "start_offset": 21,
            "end_offset": 25,
            "type": "<ALPHANUM>",
            "position": 2
        },
        {
            "token": "한글",
            "start_offset": 27,
            "end_offset": 29,
            "type": "<HANGUL>",
            "position": 3
        },
        {
            "token": "nori",
            "start_offset": 30,
            "end_offset": 34,
            "type": "<ALPHANUM>",
            "position": 4
        }
    ]
}

공백을 기준으로 5단어로 분리된 것을 확인 할 수 있습니다. 만약 한글이면 공백을 기준으로 분리되어 단어 기분으로는 맞지 않습니다. 다음 예제는 es에서 기본으로 제공하는 것에 대한 예제 입니다.

curl --location --request GET 'https://172.19.164.132:9200/_analyze?pretty=true' \
--header 'Content-Type: application/json' \
--data '{
    "analyzer": "standard",
    "text": "여기는 대한민국입니다."
}'
결과
{
    "tokens": [
        {
            "token": "여기는",
            "start_offset": 0,
            "end_offset": 3,
            "type": "<HANGUL>",
            "position": 0
        },
        {
            "token": "대한민국입니다",
            "start_offset": 4,
            "end_offset": 11,
            "type": "<HANGUL>",
            "position": 1
        }
    ]
}

 한글을 단어로 분리 하기 위해서는 여러가지 형태소 분석기가 있지만 es에서 지원하는 nori 룰 사용 하면 단어로 분리 할 수 있습니다.

curl --location --request GET 'https://172.19.164.132:9200/_analyze?pretty=true' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic ZWxhc3RpYzoxbj1lQmFzTTJqR3gxRVpGMDdEWQ==' \
--data '{
    "analyzer": "nori",
    "text": "여기는 대한민국입니다."
}'
결과
{
    "tokens": [
        {
            "token": "여기",
            "start_offset": 0,
            "end_offset": 2,
            "type": "word",
            "position": 0
        },
        {
            "token": "대한",
            "start_offset": 4,
            "end_offset": 6,
            "type": "word",
            "position": 2
        },
        {
            "token": "민국",
            "start_offset": 6,
            "end_offset": 8,
            "type": "word",
            "position": 3
        },
        {
            "token": "이",
            "start_offset": 8,
            "end_offset": 11,
            "type": "word",
            "position": 4
        }
    ]
}

자세한 학습은 다음 사이트를 참고 해 주새요 한국어(nori) 분석 플러그인 | Elasticsearch 플러그인 및 통합 [7.17]

 

Korean (nori) Analysis Plugin | Elasticsearch Plugins and Integrations [7.17] | Elastic

Korean (nori) Analysis Pluginedit The Korean (nori) Analysis plugin integrates Lucene nori analysis module into elasticsearch. It uses the mecab-ko-dic dictionary to perform morphological analysis of Korean texts. Installationedit This plugin can be instal

www.elastic.co

1-2. analyzer 과 매핑

es에서 분석한 데이터를 저장(inverted index)되고 검색 할 떄 저장된 값을 바탕으로 검색을 제공 합니다. 또한 필드를 정의 할 떄 text 타입과 keyword 타입은 신중히 결정을 해야 합니다. text는 단어를 문장에서 찾지만 keyword는 keyword analyzer을 사용하여 문장 전체가 같아야 합니다. 

2. Search API

2-1. 전체 요청

http:// 도메인 / index / _search

curl --location 'https://localhost(or ip or domain):9200/tourlist/_search?pretty=true' \
--header 'Content-Type: application/json' \

2-2 전체 인텍스 검색

http:// 도메인 / index / _search ? q =  검색어 & pretty

인텍스 전체에서 부산이 포함 되어 있는 모든 필드를 조회 합니다.

curl --location 'https://172.19.164.132:9200/tourlist/_search?q=부산pretty' \
--header 'Content-Type: application/json' \

2-3. 인텍스에서 특정 필드 검색

http:// 도메인 / index / _search ? q = 컬럼명: 검색어 & pretty

주소 필드에 '부산"이 포함 되어 있는 것 검색

curl --location 'https://localhost:9200/tourlist/_search?q=addr1:부산&pretty' \
--header 'Content-Type: application/json' \

3. RequestBody 검색

http:// 도메인 / index / _search ? pretty

옵션 내용
query 검색을 위한 쿼리 문 
form/size 조회 갯수 ( from : 시작, size :크기 ), [ 기본 ( form:0, size:n ) 으로 from 생략 가능 ]
sort 검색 결과가 _score가 아닌 필드 기준으로 정렬
_source 결과 중 특정 필드의 내용만 출력
highlight 결과 중 검색어와 매칭 되는 단어 강조
boost 결과를 스코어로 변경
scroll n개의 단위로 나뉘어서 

3-1, 주소 필드에 부산이 포함된 검색

curl --location --request GET 'https://172.19.164.132:9200/tourlist/_search?pretty=null' \
--header 'Content-Type: application/json' \ 
--data '{
    "query": {
        "term": {
            "addr1": "부산"
        }
    }
}'

3-2. 한번에 가지올 크기 지정 : from: size:

응답에 있는 hits.total.value 에 검색된 갯수기 있습니다.

curl --location --request GET 'https://172.19.164.132:9200/tourlist/_search?pretty=true' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic ZWxhc3RpYzoxbj1lQmFzTTJqR3gxRVpGMDdEWQ==' \
--data '{
    "size": 3,
    "query": {
        "term": {
            "addr1": "부산"
        }
    }
}'

결과
{
    "took": 9,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 5,
            "relation": "eq"
        },
        "max_score": 0.83591366,
        "hits": [
            {
                "_index": "tourlist",
                "_id": "A4StQYoB7JUIma-S4U-_",
                "_score": 0.83591366,
                "_source": {
                    "_class": "com.hyomee.service.elastic.tour.doc.TourListDoc",
                    "contentid": "2726843",
                    "addr1": "부산광역시 강서구 천성동",
                    ....
                }
            },
            {
                "_index": "tourlist",
                "_id": "AoStQYoB7JUIma-S4U8s",
                "_score": 0.83591366,
                "_source": {
                    "_class": "com.hyomee.service.elastic.tour.doc.TourListDoc",
                    "contentid": "129156",
                    "addr1": "부산광역시 강서구 외양포로 10",
                    ...                    
                }
            },
            {
                "_index": "tourlist",
                "_id": "BoStQYoB7JUIma-S408r",
                "_score": 0.79428625,
                "_source": {
                    "_class": "com.hyomee.service.elastic.tour.doc.TourListDoc",
                    "contentid": "2782772",
                    "addr1": "부산광역시 강서구 거가대로 2571",
                    ....
                }
            }
        ]
    }
}

3-3. 정렬 

필드명을 기준으로 정렬 : desc, asc

curl --location --request GET 'https://localhost:9200/tourlist/_search?pretty=true' \
--header 'Content-Type: application/json' \ 
--data '{
    "size": 3,
    "sort": {
        "cat1.keyword": "desc",
        "createdtime.keyword": "desc"        
    },
    "query": {
        "term": {
            "addr1": "부산"
        }
    }
}'

3-4 원하는 필드만 가져오기

주소 필드에 부산이 포함된 결과 중 title과 overview만 가져 오기

curl --location --request GET 'https://172.19.164.132:9200/tourlist/_search?pretty=null' \
--header 'Content-Type: application/json' \ 
--data '{
    "_source": ["title" , "overview"],
    "query": {
        "term": {
            "addr1": "부산"
        }
    }
}'
결과
{
    "took": 212,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 5,
            "relation": "eq"
        },
        "max_score": 0.83591366,
        "hits": [
            {
                "_index": "tourlist",
                "_id": "A4StQYoB7JUIma-S4U-_",
                "_score": 0.83591366,
                "_source": {
                    "title": "가덕도 연대봉",
                    "overview": "예로부터 더덕이 많이 나서 붙여졌다는 이름인 가덕도에 위치한 가장 높은 곳이다. 가덕도는 부산에 속한 섬 중 가장 큰 섬으로 신석기 시대부터 사람이 살았던 것으로 추정되며, 임진왜란과 일제강점기까지 우리나라의 아린 역사를 지켜본 섬이다.<br /> \n연대봉은 해발 459미터의 높이로 2~3시간이면 다녀올 수 있는 산으로 높이가 그리 높지도 않아 오르기도 어렵지 않지만 정상에 오르면 높은 산에 오른 듯한 기분과 전망을 경험할 수 있다. 산세가 원만하여 가족단위로 가볍게 등산하기에 알맞으며 정상에 가까이 오르면 가덕도 바다와 거가대교를 한 눈에 볼 수 있다.<br />\n연대봉 정상에는 임진왜란 당시 최초로 왜적을 발견해 불을 피워 올렸던 봉수대를 볼 수 있다.<br />\n산과 바다의 청취를 동시에 느낄 수 있는 곳이다."
                }
            },
            {
                "_index": "tourlist",
                "_id": "AoStQYoB7JUIma-S4U8s",
                "_score": 0.83591366,
                "_source": {
                    "title": "가덕도 등대",
                    "overview": "* 고대역사를 간직하고 있는 가덕도 등대 *<br />옛 등대 시설은 사무실과 숙소, 등탑이 연결된 복합건물 형태로써 중앙에 높이 9.2m의 등탑이 세워져 있으며, 붉은 벽돌과 미송을 사용했고 출입구 천정에는 그 당시 황실의 상징인 오얏꽃 모양의 문장이 새겨져 있으며, 함석으로 된 지붕은 부식방지를 위해 함석 위에 피치타르가 덮혀져 있다. 가덕도는 한반도의 동남단에 자리잡아 동으로는 사하구 다대포, 서남북은 거제도 동북바다, 북으로는 유라시아와 환태평양의 관문이면서 동북아 허브항만으로 건설한 부산항신항(2006.1.19)과 접하며 진해시 용원동과 접하며 진해시 용원과의 거리는 4㎞, 인근의 거제도와의 거리는 10㎞ 정도이다.<br /><br />* 가덕도는 해상교류의 요츙지 *<br />가덕도가 해상교류 및 군사적으로 중요시 된 것은 조선 중종 39년(1544년) 가덕진과 천성진을 설치하여 임진왜란 때는 치열한 격전장이기도 했던 곳이었으며, 현재 진해만으로 들어가는 중요 요충지로서 가덕도등대는 대한제국의 말기인 1909년 12월에 건립되었으며 옛 가덕도 등대건물은 서구 건축양식으로 지어진 건축물의 하나로 2003년 9월 부산시 유형문화재로 지정되었다. 또한 해양수산부에서도 영구보존 시설로 지정해 원형을 보존하고 있다. 2002년 새로 지어진 지금의 등대는 팔각으로 된 돌출형이며 등탑높이는 40.5m로 우리나라에서 두 번째로 높은 등대이다.<br /><br />* 최초점등일 - 1909년 12월 <br />* 구조 - 백팔각 콘크리트(40m)<br />* 등질 - 섬백광 12초 1섬광(FlW12s) <br />* 특징 - 낙동강 하구언에 위치하며 조선시대부터 봉화를 올려 뱃길을 안내하였던 연대봉 등 고대역사를 간직한 섬으로 등대체험학교를 운영하고 있다. <br>"
                }
            },
            {
                "_index": "tourlist",
                "_id": "BoStQYoB7JUIma-S408r",
                "_score": 0.79428625,
                "_source": {
                    "title": "가덕해양파크휴게소",
                    "overview": "부산~거제 간 연결 도로의 휴게소로 천혜의 자연을 가득 담은 풍경 맛집이다. 부산의 서쪽 끝 가덕도에 있어 드넓은 야외테라스와 힐링 산책로에서 광활한 바다 풍경을 즐길 수 있는 곳이다. 어린왕자 등 여러 가지 조형물과 벚꽃나무 군락이 있어 사진 찍기 좋은 포인트가 곳곳에 마련되어 있고, 뒤편에는 맘껏 뛰어놀 수 있는 넓은 광장과 먼바다 풍경을 조망할 수 있는 전망대도 있다. 부산~거제 간 연결 도로의 핵심인 가덕해저터널에 대한 모든 것이 전시된 세계 최대수심 해저터널 연결도로 홍보전시관도 볼거리다."
                }
            },
            {
                "_index": "tourlist",
                "_id": "BIStQYoB7JUIma-S4k8u",
                "_score": 0.75660795,
                "_source": {
                    "title": "가덕도대항인공동굴",
                    "overview": "2차 세계대전 말에 일본군은 전력이 급강하하자 부산과 주변 해안에 미군 상륙작전을 대비하기 위한 방어시설을 구축하였는데 가덕도 대항마을의 인공동굴도 이와 같은 정세에서 조성된 것으로 보인다. 가덕도 대항 인공동굴은 현재 10여 개 정도 발견되었으며 탄광 노동자들을 데려와 만들었다고 전해진다. 형태는 I자, T자, L자형 동굴과 연결 복식 동굴이 있고, 내부 통로가 십자형으로 얽혀 있을 정도로 긴 동굴도 있다. 동굴 내부에 당시 상황을 이해하기 쉽게 조형물로 표현해 놓아 가슴 아픈 역사의 흔적을 되짚어 볼 수 장소이다."
                }
            },
            {
                "_index": "tourlist",
                "_id": "AYStQYoB7JUIma-S4E_A",
                "_score": 0.75660795,
                "_source": {
                    "title": "가덕도",
                    "overview": "가덕도는 부산 최대의 섬으로 자동차로 여행하기 좋은 곳이다. 최고봉인 연대산을 비롯해 수많은 산들과 해안가를 따라 이어진 힐링 둘레길, 일제강점기의 역사 유적지 등 볼거리가 많다. 특히 아름다운 일출, 일몰과 사계절 월척이 가능한 낚시 포인트는 최고의 자랑거리이다. \n\n* 일출&일몰&낚시&차박 캠핑 포인트: \n  - 대항새바지(일출)\n  - 새바지등대(일출)\n  - 연대봉(일출/일몰)\n  - 가덕도등대(일출)\n  - 천성항(일몰/낚시)\n  - 대항전망대(일몰)\n  - 대항방파제(낚시)\n  - 새바지방파제(낚시) \n  - 외양포항(일몰/차박 캠핑)\n  - 동선새바지(일출/일몰/차박 캠핑)"
                }
            }
        ]
    }
}

 

참고 :  4.4 검색 API - _search API - Elastic 가이드북 (kimjmin.net)

 

4.4 검색 API - _search API - Elastic 가이드북

지금까지는 도큐먼트 단위의 입력, 수정, 삭제, 조회 하는 방법을 알아보았습니다. 하지만 Elasticsearch의 진가는 쿼리를 통한 검색 기능에 있습니다. 검색은 인덱스 단위로 이루어집니다. GET <인덱

esbook.kimjmin.net

참고 : https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-your-data.html

 

Search your data | Elasticsearch Guide [7.17] | Elastic

A search query, or query, is a request for information about data in Elasticsearch data streams or indices. You can think of a query as a question, written in a way Elasticsearch understands. Depending on your data, you can use a query to get answers to qu

www.elastic.co

 

'ElasticSearch' 카테고리의 다른 글

ElasticSearch Query - Aggregation  (0) 2023.09.02
ElasticSearch Query-DSL Compound queries  (0) 2023.08.30
ElasticSearch Query DSL - match, term  (0) 2023.08.30
Elasticsearch 문서 색인 / 조회  (0) 2023.08.29
Elasticsearch 연동  (0) 2023.08.15