'Engine'에 해당되는 글 2건

  1. 2018.06.27 [Elasticsearch] Move TransportClient to High Level REST Client
  2. 2018.04.19 [Elasticsearch] Synonym filter 테스트

[Elasticsearch] Move TransportClient to High Level REST Client

Elastic/Elasticsearch 2018. 6. 27. 11:46

이번에 새로 Indexer 모듈을 만들다 보니 아래 문서의 내용을 확인하게 되었습니다.


Reference)

https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/client.html

https://github.com/elastic/elasticsearch/tree/master/client/rest/src/test/java/org/elasticsearch/client


원문발췌)

We plan on deprecating the TransportClient in Elasticsearch 7.0 and removing it completely in 8.0. Instead, you should be using the Java High Level REST Client, which executes HTTP requests rather than serialized Java requests. The migration guidedescribes all the steps needed to migrate.

The Java High Level REST Client currently has support for the more commonly used APIs, but there are a lot more that still need to be added. You can help us prioritise by telling us which missing APIs you need for your application by adding a comment to this issue: Java high-level REST client completeness.

Any missing APIs can always be implemented today by using the low level Java REST Client with JSON request and response bodies.


사실 저도 TransportClient 를 사용하면 version 때문에 고민을 하긴했었는데요.

이 참에 그냥 REST Client 로 넘어 가야 겠다고 생각해서 새로 작성 하였습니다.


기본적인 예제 코드는 아래 내용 참고 하시면 됩니다.


public static void main(String[] args) {
requestRestClient();
}

public static void requestRestClient() {
int numNodes = 5; //randomIntBetween(1, 5);
HttpHost[] hosts = new HttpHost[numNodes];
for (int i = 0; i < numNodes; i++) {
hosts[i] = new HttpHost("localhost", 9200);
}
RestClientBuilder builder = RestClient.builder(hosts);
RestClient restClient = builder.build();

builder.setMaxRetryTimeoutMillis(10000);

builder.setFailureListener(new RestClient.FailureListener() {
@Override
public void onFailure(HttpHost host) {
System.out.println("onFailure");
}
});

builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(
RequestConfig.Builder requestConfigBuilder) {
return requestConfigBuilder.setSocketTimeout(10000);
}
});

Map<String, String> params = new HashMap<>();
params.put("preference", "_shards:0,1,2,3");

HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory consumerFactory =
new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(
30 * 1024 * 1024);
try {
Response response = restClient
.performRequest("GET", "/hello/_search", params, null, consumerFactory);

System.out.println(response.toString());

// Read Case 1
RequestLine requestLine = response.getRequestLine();
HttpHost host = response.getHost();
int statusCode = response.getStatusLine().getStatusCode();
Header[] headers = response.getHeaders();
String responseBody = EntityUtils.toString(response.getEntity());

System.out.println(requestLine);
System.out.println(host);
System.out.println(statusCode);
System.out.println(headers);
System.out.println(responseBody);

// Read Case 2 - old fashion
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));

String inputLine;
StringBuffer buffer = new StringBuffer();

while ((inputLine = reader.readLine()) != null) {
buffer.append(inputLine);
}

reader.close();

// System.out.println(buffer.toString());
} catch (IOException e) {
e.printStackTrace();
}

try {
restClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}

public static int randomIntBetween(int min, int max) {
return RandomNumbers.randomIntBetween(random(), min, max);
}

public static Random random() {
return RandomizedContext.current().getRandom();
}




:

[Elasticsearch] Synonym filter 테스트

Elastic/Elasticsearch 2018. 4. 19. 16:19

커뮤니티에 질문 주신 내용이 있어서 바쁘지만 테스트 결과 공유 드립니다.

커뮤니티에 질문 올려 주신 분이 계셔서 직접 테스트 진행 했습니다.

제가 position 관련 에러 수정을 위한 테스트 시간이 없어서 인명 사전 등록 방법으로 처리 했는데요.

수정이 필요 하시면 KoreanFilter 코드를 수정 하시면 됩니다.


설치 및 테스트 Elasticsearch Version)

6.0.0


Arirang plugin 설치)

$ bin/elasticsearch-plugin install https://github.com/HowookJeong/elasticsearch-analysis-arirang/releases/download/6.0.0/elasticsearch-analysis-arirang-6.0.0.zip


Index 삭제)

DELETE syntest


{

  "error": {

    "root_cause": [

      {

        "type": "index_not_found_exception",

        "reason": "no such index",

        "resource.type": "index_or_alias",

        "resource.id": "syntest",

        "index_uuid": "_na_",

        "index": "syntest"

      }

    ],

    "type": "index_not_found_exception",

    "reason": "no such index",

    "resource.type": "index_or_alias",

    "resource.id": "syntest",

    "index_uuid": "_na_",

    "index": "syntest"

  },

  "status": 404

}


Index 생성)

PUT /syntest

{

  "settings": {

    "index.number_of_shards": 1,

    "index.number_of_replicas": 0,

    "index": {

      "analysis": {

        "analyzer": {

          "arirang_custom": {

            "tokenizer": "arirang_tokenizer",

            "filter": [

              "lowercase",

              "trim",

              "custom_synonym",

              "arirang_filter"

            ]

          }

        },

        "filter": {

          "custom_synonym": {

            "type": "synonym",

            "synonyms": [

              "henry,헨리,앙리",

              "신해철,마왕"

            ]

          }

        }

      }

    }

  }

}


{

  "acknowledged": true,

  "shards_acknowledged": true,

  "index": "syntest"

}


Analyze 실행)

GET /syntest/_analyze

{

  "tokenizer": "arirang_tokenizer",

  "filter": [

    "lowercase",

    "trim",

    "custom_synonym",

    "arirang_filter"

  ],

  "text": "신해철"

}


{

  "tokens": [

    {

      "token": "신해철",

      "start_offset": 0,

      "end_offset": 3,

      "type": "korean",

      "position": 0

    },

    {

      "token": "신해",

      "start_offset": 0,

      "end_offset": 2,

      "type": "korean",

      "position": 0

    },

    {

      "token": "해철",

      "start_offset": 1,

      "end_offset": 3,

      "type": "korean",

      "position": 1

    },

    {

      "token": "마왕",

      "start_offset": 0,

      "end_offset": 3,

      "type": "SYNONYM",

      "position": 1

    }

  ]

}


동의어 처리가 되지 않은 이유)

GET /syntest/_analyze

{

  "tokenizer": "arirang_tokenizer",

  "text": "신해철은 henry"

}


{

  "tokens": [

    {

      "token": "신해철은",

      "start_offset": 0,

      "end_offset": 4,

      "type": "korean",

      "position": 0

    },

    {

      "token": "henry",

      "start_offset": 5,

      "end_offset": 10,

      "type": "word",

      "position": 1

    }

  ]

}


tokenizer 에서 추출한 토큰은 위와 같이 두개 입니다.

아래는 filter 를 적용한 내용입니다.


GET /syntest/_analyze

{

  "tokenizer": "arirang_tokenizer",

  "filter": [

    "lowercase",

    "trim",

    "custom_synonym",

    "arirang_filter"

  ],

  "text": "신해철은 henry"

}


{

  "tokens": [

    {

      "token": "신해철",

      "start_offset": 0,

      "end_offset": 3,

      "type": "korean",

      "position": 0

    },

    {

      "token": "신해철은",

      "start_offset": 0,

      "end_offset": 4,

      "type": "korean",

      "position": 0

    },

    {

      "token": "신해",

      "start_offset": 0,

      "end_offset": 2,

      "type": "korean",

      "position": 0

    },

    {

      "token": "해철",

      "start_offset": 1,

      "end_offset": 3,

      "type": "korean",

      "position": 1

    },

    {

      "token": "철은",

      "start_offset": 2,

      "end_offset": 4,

      "type": "korean",

      "position": 2

    },

    {

      "token": "henry",

      "start_offset": 5,

      "end_offset": 10,

      "type": "word",

      "position": 3

    },

    {

      "token": "헨리",

      "start_offset": 5,

      "end_offset": 10,

      "type": "SYNONYM",

      "position": 3

    },

    {

      "token": "앙리",

      "start_offset": 5,

      "end_offset": 10,

      "type": "SYNONYM",

      "position": 3

    }

  ]

}


위에 추출된 term 목록을 보면 "마왕" 이라는 동의어가 추가 되지 않은것을 볼 수 있습니다.

이것은 두 가지 방법으로 해결이 가능 합니다.

사전에 "신해철" 이라는 인명 사전 정보를 등록 하시면 됩니다.

기본적으로 tokenzier 과정 후 filter 처리가 되면서 사전에 등록된 정보로 term 구성이 되기 때문에 사전에 누락 된 경우는 일반적으로 KoreanFilter 에 의해서 bigram 처리가 됩니다.

다른 한 가지는 position 정보가 구성 시 오류가 나지 않도록 코드를 수정 하는 것입니다.

KoreanFilter 코드를 참고 하셔서 테스트 및 수정 하시면 됩니다.


아래는 사전에 "신해철" 추가 후 실행한 방법 입니다.


GET /syntest/_analyze

{

  "tokenizer": "arirang_tokenizer",

  "filter": [

    "lowercase",

    "trim",

    "arirang_filter",

    "custom_synonym"

  ],

  "text": "신해철은 henry"

}


{

  "tokens": [

    {

      "token": "신해철",

      "start_offset": 0,

      "end_offset": 3,

      "type": "korean",

      "position": 0

    },

    {

      "token": "마왕",

      "start_offset": 0,

      "end_offset": 3,

      "type": "SYNONYM",

      "position": 0

    },

    {

      "token": "henry",

      "start_offset": 5,

      "end_offset": 10,

      "type": "word",

      "position": 1

    },

    {

      "token": "헨리",

      "start_offset": 5,

      "end_offset": 10,

      "type": "SYNONYM",

      "position": 1

    },

    {

      "token": "앙리",

      "start_offset": 5,

      "end_offset": 10,

      "type": "SYNONYM",

      "position": 1

    }

  ]

}


: