키크니개발자 2022. 10. 30. 18:44

 

안녕하세요!

키크니 개발자 입니다. 🦒

 

기존에 사용하던 엘라스틱 버전 5를 7로 올려야하는 상황이어서 엘라스틱서치관련 책을 읽고 정리해보았습니다. 😁

 

ElasticSearch 이란?

루씬 기반의 오픈소스 검색 엔진이며 JSON 기반의 문서를 저장하고 검색할 수 있으며 문서들의 데이터를 기반으로 분석 작업도 할 수 있다.

ElasticSearch 특징

  • 준실시간 검색 엔진 : 실시간이라고 생각할 만큼 색인된 데이터가 매우 빠르게 검색됨
    • 준실시간성 : 문서를 입력하자마자 검색하는 것은 불가능하더라도 1초의 시간이 흐른 후에는 검색할 수 있다.  JSON 문서 를 입력하면 해당 문서는 우선 메모리에 저장된다. 그리고 1초 후에 샤드(Shard)라는 엘라스틱서치 데이터 저장 공간에 저장되고 이 이후에는 쿼리를 통해서 해당 문서를 검색할 수 있게 된다.
  • 클러스터 구성 : 한 대 이상 노드를 클러스터로 구성하여 높은 수준의 안정성을 이루고 부하를 분산할 수 있음
    • 1개 이상의 노드를 묶어 하나의 클러스터로 구성하는데 Node 1에 문제가 생겨도 해당 노드만 클러스터에서 제외 시키고 나머지 노드들로 클러스터의 구성을 유지할 수 있다.
  • 스키마리스 : 입력 될 데이터에 대해 미리 정의하지 않아도 동적으로 스키마를 생성할 수 있음
    • 입력 된 문서의 스키마를 미리 정의할 필요가 없다. 문서를 분석한 후 문서의 내용에 맞는 스키마를 동적으로 생성한다.
  • Rest API : Rest API 기반의 쉬운 인터페이스를 제공하여 비교적 진입 장벽이 낮음

문서 색인하기

간단하게 문서 저장을 한다는 것으로 이해하면 됩니다.

 

요청값

curl -X PUT "localhost:9200/user/_doc/1?pretty" -H 'Content-Type: application/json' -d'{"username":"alden.kang"}'
  • Rest API의 메서드이다. 새로운 문서를 입력할 때는 PUT, 기존 문서를 수정할 때는 POST, 삭제할 떄는 DELETE, 조회할 떄는 GET을 사용한다.
  • user : 문서를 색인할 인덱스 이름이다. 인덱스는 문서를 저장하는 가장 큰 논리적인 단위를 의미한다.
  • _doc : 문서의 타입 이름이다.
  • 1 : 문서의 ID이다. 인덱스 내에서 유일해야 하며, 같은 ID가 입력 되면 해당 문서를 수정할 수 있다.
  • 엘라스틱 서치는 문서를 색인하여 저장할 인덱스가 이미 생성되어있는지, 아니면 새로 생성해야 하는지 확인한다. 그리고 인덱스가 존재하지 않는다면 해당 인덱스를 생성한다. 이 후 타입이 존재하는지 확인한다. 타입이 존재하지 않는다면 타입도 생성한다. 이 후 스키마가 존재하는지 확인하고 없다면 스키마를 생성하고, 스키마가 있다면 색인 요청 된 문서사이의 충돌이 있는지 확인한다. 예를들어 기존에 숫자 형태로 정의된 필드에 문자 형태의 값이 들어오면 스키마 충돌이라고 판단하고 에러가 난다. 마지막으로 동일한 ID를 가진 문서가 있는지 확인한다. 만약 동일한 ID의 문서가 있다면 해당 문서의 내용을 수정하고, 그렇지 않다면 신규로 색인을 완료한다.

문서 조회하기

요청값

curl -X GET "localhost:9200/user/_doc/1?pretty"

결과값

{
    "_index":"user",
    "_type":"_doc",
    "_id":"1",
    "_version":1,
    "_seq_no":0,
    "_primary_term":1,
    "found":true,
    "_source":{
        "username":"alden.kang"
    }
}
  • _index : 어떤 인덱스인지
  • _type : 어떤 타입인지
  • _id : 문서의 ID는 무엇인지
  • _source : 문서의 내용

문서 삭제하기

요청값

curl -X DELETE "localhost:9200/user/_doc/1?pretty"

결과값

{
    "_index":"user",
    "_type":"_doc",
    "_id":"1",
    "_version":2,
    "reulst":"deleted",
    "_shards": {
        "total":2,
        "successful":1,
        "failed": 0
    },
    "_seq_no":0,
    "_primary_term":1
}
  • _result : 삭제되었음을 볼 수 있다.

삭제 된 문서 조회하기

요청값

curl -X GET "localhost:9200/user/_doc/1?pretty"

결과값

{
    "_index":"user",
    "_type":"_doc",
    "_id":"1",
    "found":false     
}

문서 수정하기

요청값

curl -X PUT "localhost:9200/contents/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
	"title":"How to use ElasticSearch",
	"author":"alden.kang, benjamin.butn"
}'

결과값

{
    "_index":"contents",
    "_type":"_doc",
    "_id":"1",
    "_version":2,1,
    "result":"updated",
    "_shards": {
        "total":2,
        "successful":1,
        "failed": 0
    },
    "_seq_no":1,
    "_primary_term":1
}
  • _version : 1에서 2로 바뀌었다.
  • results : created → updated로 바뀌었다.

스키마 확인하기

요청값

curl -s http://localhost:9200/contents/_mappings?pretty

결과값

{
    "contents" : {
        "mappings" : {
            "_doc" : {
                "properties" : {
                    "author" : {
                        "type":"text",
                        "fields" : {
                            "keyword" : {
                                "type" : "keyword",
                                "ignore_above" : 256
                            }
                        }
                    },
                    "title" : {
                        "type":"text",
                        "fields" : {
                            "keyword" : {
                                "type" : "keyword",
                                "ignore_above" : 256
                            }
                        }
                    }
            
                }
            }
        }
    }
}

새로운 필드 색인하기

해당 문서에 rating 필드를 추가하면 동적으로 스키마에 추가된다.

curl -X PUT "localhost:9200/contents/_doc/2?pretty" -H 'Content-Type: application/json' -d'
{
	"title":"How to use ElasticSearch",
	"author":"alden.kang, benjamin.butn"
	"rating": 5.0
}'
  • 위의 문서가 색인 된 채로 아래와 같이 필드의 값을 넣게 되면 “mapper_parsing_exception”, “status”:400에러가 발생한다.
  • 스키마리스라고는 하지만 스키마 정의가 아예 없는 것은 아니다. 그렇기 때문에 중간에 필드 형태가 바뀌는 것까지 알아서 잡아주는 것은 아니다.
curl -X PUT "localhost:9200/contents/_doc/2?pretty" -H 'Content-Type: application/json' -d'
{
	"title":"How to use ElasticSearch",
	"author":"alden.kang, benjamin.butn"
	"rating": "N/A"
}'

풀 스캔 쿼리

  • q=* : q는 쿼리를 *은 모든 단어를 의미한다.

요청값

curl -X GET "localhost:9200/books/_search?q=*&pretty"

결과값

{
    "took": 27,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 10,
        "max_source": 1.0,
        "hits": [
            {
                "_index": "books",
                "_type": "_doc",
                "_id": "5",
                "_score": 1.0,
                "_source": {
                    "title": "Kubernates: Up and Running",
                    "authors": "Joe Beda, Brendan Burns",
                    "topics": "Google / Information Technology / Operations",
                    "rating": 5.0,
                    "reviews": 33

                }
            }
        ]
    }
}
  • took : 검색에 소요된 시간
  • total : 검색에 참여한 샤드의 개수
  • hits.total : 검색 결과의 개수

특정 문자열 찾기

요청값

curl -X GET "localhost:9200/books/_search?q=elasticsearch&pretty"

rating 기준으로 검색하기

요청값

curl -X GET "localhost:9200/books/_search?pretty" -H 'Content-Type: applicalhost/json' -d'
{
	"query" : {
		"match" : {
			"rating": 5.0
		}
	}
}'

범위쿼리

  • 필터가 적용 된 쿼리 이다.
  • 예 : 성별이 남자인지 여자인지를 찾기 위해서는 남자인가 아닌가로 검색하지만, 서울 특별시에 사는 사람들을 찾기 위해서는 주소에 서울특별시가 들어있는지를 검색한다.
  • 필터와 쿼리의 차이점
    • 필터 : 예/아니오로 구분하는 방식
    • 쿼리 : 문자열 안에 특정 문자가 포함되어있는지 아닌지를 확인하는 과정
curl -X GET "localhost:9200/books/_search?pretty" -H 'Content-Type: applicalhost/json' -d'
{
	"query" : {
		"bool" : {
			"must": { "match_all" : {}},
            "filter" : {
                "range": {
                    "reviews": {
                        "gte": 10
                    }
                }
            }
		}
	}
}'

문서 분석하기

  • 엘라스틱서치는 검색 작업을 바탕으로 분석작업도 할 수 있다.
  • 예 : 서울에 살고 있는 사람이 몇 명인지, 특정 기술을 가지고 있는 사람이 몇명인지 통계를 만들 수 있다.
  • 분석작업은 aggregation이라고 부르며 search API 기반으로 진행된다.
  • topics에 나오는 단어 빈도 세기

요청값

curl -X GET "localhost:9200/books/_search?pretty" -H 'Content-Type: applicalhost/json' -d'
{
	"size" : 0, 
    "aggs" : {
        "group_by_state" : {
            "terms" : {
                "field" : "topics.keyword"
            }
        }
    }
}'

결과값

  • Web Service라는 토픽이 가장 많이 포함되어 있음을 알 수 있다.
{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 10,
        "max_source": 1.0,
        "hits": [],
        "aggregations" : {
            "group_by_state" : {
                "doc_count_error_uper_bound" : 0,
                "sum_other_doc_count" : 0,
                "buckets" : [
                    {
                        "key" : "Web Server",
                        "doc_count": 3
                    },
                    {
                        "key" : "Google / Infomation Technology / Operations",
                        "doc_count": 1
                    }
                ]
            }
        }
            
    }
}

토픽별 평균내기

  • 이런 형태 분석 작업은 사용자의 트렌드 분석에도 사용할 수 있다.

요청값

curl -X GET "localhost:9200/books/_search?pretty" -H 'Content-Type: applicalhost/json' -d'
{
	"size" : 0, 
    "aggs" : {
        "group_by_state" : {
            "terms" : {
                "field" : "topics.keyword"
            },
            {
                "aggs" : {
                    "average_reviews" {
                        "avg" : {
                            "field" : "reviews"
                        }
                    }
                }
            }
        }
    }
}'

결과값

{
    "took": 12,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 10,
        "max_source": 1.0,
        "hits": [],
        "aggregations" : {
            "group_by_state" : {
                "doc_count_error_uper_bound" : 0,
                "sum_other_doc_count" : 0,
                "buckets" : [
                    {
                        "key" : "Web Server",
                        "doc_count": 3,
                        "average_revies" : {
                            "value" : "8.666666666666"
                        }
                    },
                    {
                        "key" : "Google / Infomation Technology / Operations",
                        "doc_count": 1,
                        "average_revies" : {
                            "value" : "33.0"
                        }
                    }
                ]
            }
        }
            
    }
}

 

 

 

 

 

 

References

- 기초부터 다지는 ElasticSearch 운영 노하우 

http://www.yes24.com/Product/Goods/96520155

 

반응형