[Elasticsearch] 엘라스틱서치 벼락치기(2) - 데이터처리
[Elastic] 1. Elastic 자동완성 가이드 (Autocomplete Guide) - Prefix Queries
참고한 도서📚: 시작하세요! 엘라스틱 서치
앞서 언급했지만 한 번 더 복습할 겸 정리하고 넘어가겠다!
엘라스틱 서치의 구조는 관계형 데이터베이스와 비교해서 다음과 같이 이해하면 된다.
유닉스에서 엘라스틱서치의 REST API를 이용한 curl 명령은 다음과 같은 형식으로 사용한다.
curl -X{메서드} http://host:port/{인덱스}/{타입}/{도큐먼트 id} -d '{데이터}'
유닉스의 curl 명령어로 입력해도 되지만 편의상 Postman으로 데이터 처리를 다루려고 한다.
PUT 메서드와 함께 /index/type/documentid
를 입력하면 자동으로 해당 데이터가 생성이 되며 만약 index나 type이 존재하지 않는 경우 Elasticsearch에서 자동으로 만들어준다.
만약 document id를 자동으로 생성되게 하고 싶다면 type까지만 지정해주고 POST 매핑을 하면 된다. 이 경우 자동으로 id가 생성된다.
레퍼런스를 찾아보니 ElasticSearch 버전 8부터는 type 등록의 방식이 바뀌어서 이와 같이 uri로 등록이 불가능하다고 한다.
당시에 쓰던 버전이 8.1.2여서 해당 방법이 실행되지 않고 위와 같은 에러가 나는 것이었다.
버전에 맞는 방법을 찾아서 할 수도 있지만 예시나 레퍼런스가 많이 없기도 하고 아직 새 버전이 나온지 얼마 안되었기도 해서 그냥 기존의 버전7을 다시 다운받아서 하기로 했다.
새로 다운받은 elasticSearch 에서는 잘 돌아가는 것을 확인할 수 있었다!
다시 한 번 PUT 메서드로 같은 인덱스, 타입, 아이디 값을 가진 도큐먼트를 입력하면 기존의 데이터가 삭제되고 새로 입력한 데이터가 덮어 씌워진다.
엘라스틱서치에서는 입력된 도큐먼트를 수정할 수 있는 _update API를 제공한다.
도큐먼트 데이터의 업데이트는 _update API의 두 개의 매개 변수인 doc와 script를 이용해서 데이터를 제어할 수 있다.
doc 매개변수는 도큐먼트에 새로운 필드를 추가하거나 기존 필드 값을 변경하는 데 사용한다.
scrip 매개변수는 좀 더 복잡한 프로그래밍 기법을 사용해서 입력된 내용에 따라 필드의 값을 변경하는 등의 처리에 사용한다.
_update API는 POST 메서드를 사용하며 다음과 같은 URI를 사용한다.
curl -XPOST httpL//host:port/인덱스/타입/도큐먼트id/_update -d'업데이트 명령어'
이 방법이 단순히 위에서 언급한 PUT 메서드를 사용해서 데이터를 수정하는 것과 다른 이유는,
PUT 메서드로 데이터를 수정하는 경우 기존의 데이터가 삭제되고 새로 입력한 데이터가 덮어 씌워지지만
_update API는 추가할 데이터만 추가할 수 있기 때문이다
예를 들어 books/book/1에 다음과 같은 데이터가 있다고 하자
"category": "book",
"title": "elasticsearch"
여기서 만약 저자인 author 필드를 추가하고 싶다면
{
"category": "book",
"title": "elasticsearch",
"author": "lee"
}
{
"doc" : {"author": "lee"}
}
이 때 위의 방식은 doc으로 매개변수를 준 것이므로 매개변수인 doc을 명시해야 한다
위의 doc 매개변수는 비교적 단순한데 반해, script는 _source에 있는 도큐먼트의 내용에 다양한 연산을 적용할 수 있다.
script는 MVEL 언어의 문법을 사용해서 처리된다.
_source에 있는 도큐먼트의 내용을 변경하려면 script의 ctx._source
명령을 사용한다.
예를 들어 books/book/1의 source에 "page" : 250 이라고 하면 이 값을 script 명령으로 50을 더할 수 있다.
post 매핑으로 books/book/1/_update 를 uri로 줄 때
{
"script":"ctx._source.page += 50"
}
위와 같은 body를 날리면 해당 source의 page가 50 증가되어 update 된다.
이번에는 좀 더 심화해서 기존의 book의 source 중 author에 lee만 있던 것을 kim을 추가한 배열 형태로 만들어보자
1. 우선 doc 매개변수로 단일 데이터인 lee를 배열 형태로 변경한다
{
"doc":
{
"author":["Lee"]
}
}
2. 이후 script 매개변수로 author 필드에 kim을 추가한다.
🌟배열에 특정 값을 추가하려면 추가하려는 값을 특정 변수에 저장한 후. += 연산을 통해 그 변수를 추가하고자 하는 배열 필드에 추가한다.
{
"script":{
"source" : "ctx._source.author.add(params.new_author)",
"params" : { "new_author" : "Kim"}
}
}
만약 배열 형태로 만들지 않고 그냥 += 연산을 하면 LeeKim과 같이 String끼리 합쳐지므로 주의해야 한다.
이번에는 if문을 써서 조건문을 처리해보자
author 필드에 kim이 포함되어 있으면 page를 100으로 그렇지 않으면 200으로 설정할 것이다.
값을 포함하고 있는지는 자바 문법 그대로 contains를 쓰면 된다.
{
"script": {
"source": "if(ctx._source.author.contains(params.auth)) {ctx._source.page = 100} else {ctx._source.page = 200}",
"params" : {"auth" : "Kim"}
}
}
contains() 함수 외에 자바 언어에서 사용하는 ==. =<.!=과 같은 비교 연산도 사용할 수 있다.
{
"script": {
"source": "if(ctx._source.page <= params.page_count) {ctx.op = \"delete\"}else{ ctx.op = \"none\"}",
"params" : {"page_count" : 100}
}
}
{
"script": {
"source": "ctx._source.counter += params.count",
"params" : {"count" : 1}
},
"upsert" : {"counter":0}
}
DELETE 메서드를 써서 도큐먼트 데이터를 삭제하더라도 도큐먼트의 메타 정보는 여전히 남아있다. 도큐먼트의 삭제는 도큐먼트가 실제로 삭제되는 것이 아니라 도큐먼트의 _source에 입력된 데이터 값이 빈 값으로 업데이트되고 검색되지 않게 상태가 변경되는 것으로 이해하는 것이 편하다.
DELETE 메서드를 사용한 삭제 명령은 타입과 인덱스 단위로도 사용 가능하다.
이 때는 도큐먼트 단위로 데이터를 삭제했을 때와는 달리 도큐먼트의 메타 정보까지 모두 삭제된다.
도움되었어요