[Elasticsearch] failed to obtain node locks

elasticsearch 를 사용하다가 갑자기 종료가 되고 나중에 다시 시작하려고하니 아래와 같은 에러가 발생 하였다.

java.lang.IllegalStateException: failed to obtain node locks, tried [[/home/morriskim/elasticsearch/data/es-cluster]] with lock id [0]

[2019-06-21T10:22:46,024][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [spark01] uncaught exception in thread [main]
org.elasticsearch.bootstrap.StartupException: java.lang.IllegalStateException: failed to obtain node locks, tried [[/home/morriskim/elasticsearch/data/es-cluster]] with lock id [0]; maybe these locations are not writable or multiple nodes were started without increasing [node.max_local_storage_nodes] (was [1])?
        at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:125) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:112) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) ~[elasticsearch-cli-6.2.2.jar:6.2.2]
        at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-6.2.2.jar:6.2.2]
        at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:85) ~[elasticsearch-6.2.2.jar:6.2.2]
Caused by: java.lang.IllegalStateException: failed to obtain node locks, tried [[/home/morriskim/elasticsearch/data/es-cluster]] with lock id [0]; maybe these locations are not writable or multiple nodes were started without increasing [node.max_local_storage_nodes] (was [1])?
        at org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:244) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.node.Node.<init>(Node.java:264) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.node.Node.<init>(Node.java:246) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:213) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:213) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:323) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:121) ~[elasticsearch-6.2.2.jar:6.2.2]
        ... 6 more

stackoverflow에 찾아보니 jps로는 확인이 되지는 않지만 똑같은 머신에 elasticsearch 가 사용되는 경우가 있다고 하는데 아래와 같이 찾아서 프로세스를 종료하고 다시 시작 해보았다.

[morrrskim@spark01 bin]$ netstat -nlp | grep 9200
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp6       0      0 :::9200                 :::*                    LISTEN      3376/java
[morrrskim@spark01 bin]$ kill 3376
[morrrskim@spark01 bin]$ netstat -nlp | grep 9200
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)

잘 시작된다.

해결 완료

참고

https://stackoverflow.com/questions/28932178/elasticsearch-failed-to-obtain-node-lock-is-the-following-location-writable

SuggestAPI 소개

사용자가 키워드를 잘못 입력했거나 검색한 결과가 없을 경우

도큐먼트 내에 존재하는 단어를 대상으로 비슷한 키워드를 변경해서 제시하는 교정기능을 제공

  • Term Suggest API : 추천단어 제안
    잘못된 철자에 대해 해당 인덱스의 특정 필드에서 가장 유사한 단어를 추천해주는 오타교정 방법
  • Completion Suggest API : 자동완성 제안
    사용자가 입력을 완료하기 전에 자동완성을 사용해 검색어를 예측해서 보여주며, 사용자가 검색하는데 도움을 줌
  • Phrase Suggest API : 추천 문장 제안
  • Context Suggest API : 추천 문맥 제안

Term Suggest API

편집 거리를 사용해 비슷한 단어를 제안

편집거리 척도란 어떤 문자열이 다른 문자열과 얼마나 비슷한가를 편집거리를 사용해 알아볼 수 있으며, 두 문자열 사이의 편집 거리는 하나의 문자열을 다른 문자열로 바꾸는데필요한 편집 횟수를 말한다.

측정 과정에서 한 문자열을 다른 문자열로 바꿀때, 삽입, 삭제, 치환하는 연산을 포함해서 척도 측정

POST movie_term_suggest/_search
{
  "suggest":{
    "spell-suggestion": {
      "text": "lave",
      "term": {
        "field": "movieNm"
      }
    }
  }
}

Movie_term_suggest 인덱스 안에 lave가 존재 하지 않으므로 유사한 단어를 추출해서 제공 되는데, 여기서 love라는 단어와 lover이라는 단어가있을 경우에 문자치환 및 추가에 대한 척도가 적은 love가 우선순위의 점수로 매겨짐

한글은 ICU 분석기를이용하여 오타를 교정하는 것이 가능하다.

ICU 분석기 : 국제화 처리를 위해 특별히 개발된분석기

필터는 한국어 자소를 분해하는 기능과 자소를 합치는 기능을 모두 갖추고 있다.

Completion Suggest API

효율적인 검색을 위해 자동완성 기능을 제공

자동완성은 글자가 입력될 때마다 결과를 보여줘야 하기 때문에 응답 속도가 중요

엘라스틱 서치에서는 내부적으로 FST( Finite State Transducer) 를 사용

FST : 검색어가 모두 메모리에 로드되어 서비스되는 구조

색인중에 FST를 작성하여 성능 최적화를 한다.

자동완성을 위해서는 데이터 타입을 completion으로 설정 해서 인덱스를 생성해야한다.

completion 참고 사이트 (https://www.elastic.co/guide/en/elasticsearch/reference/6.5/search-suggesters-completion.html)

PUT name_completion
{
  "mappings":{
    "_doc":{
      "properties":{
        "name":{
            "type": "completion"          
        }
      }
    }
  }
}

예제 데이터

PUT name_completion/_doc/1
{
  "name": "morris kim"
}
PUT name_completion/_doc/2
{
  "name": "daniel kim"
}
PUT name_completion/_doc/3
{
  "name": "morris park"
}
PUT name_completion/_doc/4
{
  "name": "daniel park"
}
PUT name_completion/_doc/5
{
  "name": "maris kim"
}

Suggest api를 사용해보자 suggest 쿼리는 다음과 같다.

( completion에 다양한 속성을 지원한다.(Fuzzy, regex) elasticsearch api 참고)

POST name_completion/_search
{
  "suggest":{
    //name_completion은 이름변경 가능
    "name_completion":{
      "prefix": "m",
      "completion":{
        "field": "name",
        "size" :5
      }
    }
  }
}

Prefix : 전방 일치 검색기능이기 때문에 m으로 시작하는 단어만 검색이 된다.

그렇기 때문에 부분 검색을 하기 위해서는 텍스트를 나눠서 배열형태로 만들어야한다.

변경한 예제 데이터

PUT name_completion/_doc/1
{
  "name": {
    "input": [
      "morris",
      "kim"
    ]
  }
}
PUT name_completion/_doc/2
{
  "name": {
    "input": [
      "daniel",
      "kim"
    ]
  }
}
PUT name_completion/_doc/3
{
  "name": {
    "input": [
      "morris",
      "park"
    ]
  }
}
PUT name_completion/_doc/4
{
  "name": {
    "input": [
      "daniel",
      "park"
    ]
  }
}
PUT name_completion/_doc/5
{
  "name": {
    "input": [
      "maris",
      "kim"
    ]
  }
}

이제는 prefix 부분에 m 뿐만 아니라 k를 적어도 부분적으로 검색이 가능하다

참고 도서 :

https://wikibook.co.kr/practical-elasticsearch/

특정 가사를 검색하면 노래의 타이틀을 검색하는 프로그램 짜기

예제 데이터는 다음과 같다.

{
     "title" : "사랑에 연습이 있었다면",
     "singer ":"임재현",
     "lyrics":"사랑에 연습이 있었다면
                우리는 달라졌을까
                내가 널 만난 시간 혹은 그 장소
                상황이 달랐었다면
                우린 맺어졌을까
                하필 넌
                왜 내가 그렇게 철없던 시절에
                나타나서 그렇게 예뻤니
                너처럼 좋은 여자가
                왜 날 만나서 그런
                과분한 사랑 내게 줬는지
                우리 다시 그때로 돌아가자는게
                그게 미친말인가
                정신나간 소린가
                나는 더 잘 할 수 있고
                다신 울리지 않을
                자신있는데 그게 왜 말이 안돼
                시간이 너무 흘러 알게되었는데
                너를 울리지 않고 아껴주는법
                세월은 왜 철없는 날
                기다려주지 않고
                흘러갔는지 야속해
                지금 너 만나는 그에게도
                내게 그랬던 것처럼
                예쁘게 웃어주니
                너처럼 좋은 여자의
                사랑 받는 그 남자 너무 부러워
                넌 행복하니
                니옆에 지금 그 남자가 있는게
                우리 다시 맺어질수가 없는 이윤가
                나는 더 잘 할 수 있고
                다신 울리지 않을
                자신있는데 그게 왜 말이 안돼
                시간이 너무 흘러 알게 되었는데
                너를 울리지 않고 아껴주는 법
                세월은 왜 널 잊는 법을
                알려주지 않고 흘러갔는지"

}

순서 :

  1. elasticsearch analyzer nori 사용 맵핑 설정

  2. 데이터 삽입하기

  3. 가사 검색해보기

  4. Elasticsearch Analyzer Nori 적용하기

가사를 검색할것이기 때문에 text 데이터타입을 사용하자!! text 데이터 타입은 전문 검색이 가능하다는 점이 특징
text 타입으로 데이터를 색인하면 전체 텍스트가 토큰화되어 새엉되며 특정 단어를 검색하는 것이 가능해진다.

PUT lyricsSearch
{
    "settings":{
        "index":{
            "analysis":{
                "tokenizer":{
                    "nori":{
                        "type":"nori_tokenizer",
                        "decompound_mode":"mixed",
                        "user_dictionary":"userdict_ko.txt"
                    }
                },
                "analyzer":{
                    "my_analyzer":{
                        "type":"custom",
                        "tokenizer":"nori"
                    }
                }
            }
        }
    },
    "mappings":{
        "_doc":{
            "properties":{
                "lyrics":{
                    "type":"text"
                },
                "singer":{
                    "type":"keyword"
                },
                "title":{
                    "type":"text"
                }
            }
        }
    }
}

검색하는 쿼리는 다음과 같다.

GET lyrics_search/_search
{
  "query":{
    "match":{
      "lyrics": "사랑"
    }
  }
}

제대로 나오는 것 같다.

이렇게 긴 텍스트는 어떻게 인덱싱 되는지 알아보기 위해 확인 해보았다.

POST lyrics_search/_analyze
{
  "analyzer":"my_analyzer",
  "text": "사랑에 연습이 있었다면 우리는 달라졌을까 내가 널 만난 시간 혹은 그 장소 상황이 달랐었다면 우린 ..."
}

결과는 아래와 같이 토큰이 나누어 있었다.

  {"tokens" : [
    {
      "token" : "사랑",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "에",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "연습",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "이",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "word",
      "position" : 3
    },
    ...
    {
      "token" : "달라졌",
      "start_offset" : 17,
      "end_offset" : 20,
      "type" : "word",
      "position" : 9,
      "positionLength" : 2
    },
    {
      "token" : "달라지",
      "start_offset" : 17,
      "end_offset" : 20,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "었",
      "start_offset" : 17,
      "end_offset" : 20,
      "type" : "word",
      "position" : 10
    }
    ...]}
    }

위와 같은 이유는 tokenizer nori 모드를 mixed 모드를 사용했기 때문에 사랑에 라는 단어는 사랑, 에 두 가지로 나타난다.

nori tokenizer에서 decompound_mode를 discard 로 적용하였을때

{
  "tokens" : [
    {
      "token" : "사랑",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "에",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "연습",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "이",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "word",
      "position" : 3
    }
    ...
    {
      "token" : "달라지",
      "start_offset" : 17,
      "end_offset" : 20,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "었",
      "start_offset" : 17,
      "end_offset" : 20,
      "type" : "word",
      "position" : 10
    },

nori에서 tokenizer 에서 decompound_mode 모드를 none으로 입력하였을때

{
  "tokens" : [
    {
      "token" : "사랑",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "에",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "연습",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "이",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "있",
      "start_offset" : 8,
      "end_offset" : 9,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "었",
      "start_offset" : 9,
      "end_offset" : 10,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "다면",
      "start_offset" : 10,
      "end_offset" : 12,
      "type" : "word",
      "position" : 6
    },
  ....
    {
      "token" : "달라졌",
      "start_offset" : 17,
      "end_offset" : 20,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "을까",
      "start_offset" : 20,
      "end_offset" : 22,
      "type" : "word",
      "position" : 10
    },
...

각 모드마다 다르기 때문에 match 쿼리를 사용해서 더 어느정도까지 검색을 할것인지에 대해 잘 생각하고 해야할것 같다.

'BackEnd > ElasticSearch' 카테고리의 다른 글

[Elasticsearch] failed to obtain node locks  (0) 2019.06.21
SuggestAPI 소개  (0) 2019.06.10
Elasticsearch Nori  (0) 2019.05.27
Elasticsearch 모니터링 툴  (0) 2019.03.04
Elasticsearch logger  (0) 2019.02.25

Nori 적용하기

한글 형태소 분석기 Nori 적용하기

https://www.elastic.co/guide/en/elasticsearch/plugins/6.4/analysis-nori.html

Nori 형태소 분석기

루씬 프로젝트에서 공식적으로 제공되는 한글 형태소 분석기 6.4버전에서 공식적으로 릴리즈 됨

기존 형태소 분석기에 비해 30% 이상 빠르고 메모리 사용량도 현저하게 줄었으며, 시스템 전반에 영향을 주지 않게 최적화 됐다.

라이센서는 아파리라이선스 2.0 으로 채택

Nori는 서드파티 플러그 인과 달리 루씬에서 공식적으로 지원

$elasticsearch-plugun install analysis-nori

Nori 분석기

  • nori_tokenizer
  • nori_part_of_speech : 토큰 필터
  • nori_readingform : 토큰 필터

Nori_tokenizer

decompound_mode

  • none : no decomposition (분해 하지 않음)

    가거도항
    가곡역
  • discard :기본 값

    가곡역 => 가곡, 역
  • mixed : 기본적인 분할과 오리지날 단어를 함꼐 출력

    가곡역 => 가곡역, 가곡, 역

user_dictionary

nori tokenizer는 me cab-ko-dic dictionary( https://bitbucket.org/eunjeon/mecab-ko-dic/src/master/) (은전한잎)를 기본적으로 사용한다.

다음과 같은 포맷이 될수 있다.

<token> [<token1> ... <token n>]

첫번째의 토큰은 필수이며, 사전에 추가해야하는 사용자 지정 명사를 나타낸다.

복합 명사의 경우에는 첫번째 토큰( [< token1> …]) 을 제공한다.

복합 명사의 세분화는 decompound_mode 설정에 의해 제어된다.

$ES_HOME/conf/userdic_ko.txt 에 아래와 같은 데이터를 입력한다.

삼성전자 삼성 전자

userdic_ko.txt 파일에 위와 같이 설정을 하여도 decompound_mode 에 따라 영향을 받는다.

mixed 를 사용하면 복합 명사의 토큰을 분리한 거 + 복함명사를 구성하는 token 이 출력되며,

discard를 사용하면 삼성, 전자 만 출력

none을 사용하면 삼성전자 만 출력 될 것이다.

예제 테스트

analyzer

: 토크나이저를 활용하여 데이터를 테스트 해보자!!

PUT nori_sample
{
  "settings": {
    "index": {
      "analysis": {
        "tokenizer": {
          "nori_user_dict": {
            "type": "nori_tokenizer",
            "decompound_mode": "mixed",
            "user_dictionary": "userdict_ko.txt"
          }
        },
        "analyzer": {
          "my_analyzer": {
            "type": "custom",
            "tokenizer": "nori_user_dict"
          }
        }
      }
    }
  }
}

My_analyze 라는 사용자 분석기를 만들었다. 내부적으로는 은전한잎이 추가되어있음

쿼리

아래의 쿼리는 유저가 만든 유저 사전을 통해서 analyzer를 적용하여 테스트를 해보는 것이다.

POST nori_sample/_analyze
{
  "analyzer": "my_analyzer",
  "text":"삼성전자"
}

결과 :

{
  "tokens" : [
    {
      "token" : "삼성전자",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "word",
      "position" : 0,
      "positionLength" : 2
    },
    {
      "token" : "삼성",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "전자",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "word",
      "position" : 1
    }
  ]
}

결과는 잘나온다.

테스트가 아닌 검색을 해보자 !!

Term 쿼리를 사용하여 전자 만 사용했을 경우에는 잘 될까??

POST nori_sample/_doc/
{
  "title": "삼성전자"
}

GET nori_sample/_search
{
  "query":{
    "terms":{
      "title": ["전자"]
    }
  }
}
GET nori_sample/_search
{
  "query": {
    "bool": {
      "must": {
        "term": {
          "title": "삼성전자"
        }
      }
    }
  }
}
POST nori_sample/_mapping/_doc
{
  "properties": {
    "full_text": {
      "type": "text"
    }
  }
}

POST nori_sample/_doc
{
  "full_text":"삼성전자"
}

맵핑 파일의 타입까지 변경하고 찾아 보았다 하지만 다 검색이 안된다.

왜 검색이 안되나 했는데 이유는 다음과 같다 ..사용자 추가 analyzer는 은전한잎 이기 때문에 .......


term 쿼리
query: term: 필드: 질의어
term 필터와 똑같이 동작하는데, term 필터와는 달리 연관성 점수를 매긴다.

예) 키워드가 민주노총인 문서

GET /_search
{
  "query": {
    "term": {
      "keyword": "민주노총"
    }
  }
}
이것 대신 match 쿼리를 사용하는 것이 좋다. term 쿼리는 저수준의 쿼리로 직접 사용할 필요가 없다. 그리고 은전한닢 분석기로 분석된 한글은 분석을 거치지 않은 한글과는 텀이 일치하지 않으므로 분석을 돌린 필드에는 term 쿼리로 선택이 안 된다.

참고 : https://bakyeono.net/post/2016-08-20-elasticsearch-querydsl-basic.html#%ED%95%84%ED%84%B0%EC%9D%98-%EC%BA%90%EC%8B%9C-%EC%9B%90%EB%A6%AC

'BackEnd > ElasticSearch' 카테고리의 다른 글

[Elasticsearch] failed to obtain node locks  (0) 2019.06.21
SuggestAPI 소개  (0) 2019.06.10
Nori 사용 해서 노래 가사 검색하기  (0) 2019.06.10
Elasticsearch 모니터링 툴  (0) 2019.03.04
Elasticsearch logger  (0) 2019.02.25
ElasticSearch 모니터링툴 설치하기

ElasticSearch 모니터링툴 설치하기

두가지 종류가 있음

apache elasiticHQ

 

install HQ

 

 

Kibana monitoring

두 번째는 elasticsearch의 모니터링툴

6.5 부터는 모니터링툴이 자동으로 포함되어잇지만 이전버전들은 설치 해야함 .

 

 

현재 사용중인 6.2.2 에서는 kibana monitoring 을 사용하려면 xpack 설치가 필요

elasticsearch와 kibana 에 x-pack 설치 (sudo 권한)

설치를 하면 bin 디렉토리안에 x-pack 폴더가 생긴다 폴더에 들어가서 비밀번호 설정을 할것이다.

 

kibana xpack 설치

kibana 홈디렉토리의 bin디렉토리로 이동

 

 

kiabana 비밀번호 설정

xpack 을 설치하면 보안이 복잡하다 그렇기 때문에 나는 사용하지 않기로 함 !!

elasticsearch.yml 파일과 kibana.yml 파일에 다음과 같이 추가해줘야함

 

설정 후에 elasticsearch 를 종료하고 다시 시작해야한다.

 

 

참고자료

https://www.elastic.co/guide/en/elasticsearch/reference/6.2/installing-xpack-es.html

http://www.kwangsiklee.com/2017/02/%EC%97%98%EB%9D%BC%EC%8A%A4%ED%8B%B1%EC%84%9C%EC%B9%98%EC%97%90%EC%84%9C-x-pack%EC%9C%BC%EB%A1%9C-%EC%9D%B8%EC%A6%9Dauthentication-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0/

 

 

'BackEnd > ElasticSearch' 카테고리의 다른 글

[Elasticsearch] failed to obtain node locks  (0) 2019.06.21
SuggestAPI 소개  (0) 2019.06.10
Nori 사용 해서 노래 가사 검색하기  (0) 2019.06.10
Elasticsearch Nori  (0) 2019.05.27
Elasticsearch logger  (0) 2019.02.25
logger

Elasticsearch logger

로그 엔트리 3개

  1. 메인로그 (cluster-name.log)

: 동작 중 일때, 무슨일이 일어났는지에 관한 일반적인 정보를 알수 있다. 쿼리 실패, 새로운 노드 클러스터에 추가

  1. 느린 검색 로그(cluster-name_index_search_slowlog.log)

쿼리가 너무 느리게 실행될때 로그를 남기는 곳

  1. 느린 색인 로그(cluster-name_index_indexing_slowlog.log)

느린 검색로그와 유사하지만 기본으로 색인 작업이 일정 시간 지나면 로그를 남기는 곳

 

실행 중이기 때문에 curl 을 이용해서 바로 적용

 

 

 

 

https://stackoverflow.com/questions/21749997/see-all-executed-elasticsearch-queries

'BackEnd > ElasticSearch' 카테고리의 다른 글

[Elasticsearch] failed to obtain node locks  (0) 2019.06.21
SuggestAPI 소개  (0) 2019.06.10
Nori 사용 해서 노래 가사 검색하기  (0) 2019.06.10
Elasticsearch Nori  (0) 2019.05.27
Elasticsearch 모니터링 툴  (0) 2019.03.04

+ Recent posts