이번 글에서는 한 번의 API 요청으로 대량으로 document를 추가하고 조회하는 방법에 대해 알아보겠습니다.
1. MultiSearch API ( 링크 )
예를 들어 ES 서버에서 이메일 주소를 검색하는 상황을 가정해보겠습니다.
이메일 주소를 검색하기 위한 query DSL을 ES 서버에서 작성하고, Client에서는 해당 서버의 API를 호출하기만 하면 데이터를 받을 수 있습니다.
그런데 검색해야 할 이메일 주소가 100개라면 총 100번의 API를 호출해야 합니다.
이는 네트워크 비용이 발생하기 때문에 오류가 발생할 수 있으며, 성능 상의 이슈가 있을 수 있습니다.
따라서 한 번의 호출로 100개의 데이터를 조회하는 방법이 필요한데, ES에서는 이를 MultiSearch API로 제공합니다.
1) json 파일 작성
MultiSearch API를 사용하는 방법은 간단합니다.
json 파일을 생성해서 다음과 같은 포맷으로 쿼리를 작성하면 됩니다.
# vi query.json
{"index" : "test"} {"query" : {"match_all" : {}}, "from" : 0, "size" : 10} {} {"query" : { "term" : { "address" : "street" }}}
연속된 2개의 json이 header와 body로 나뉘어 하나의 쌍을 이루며, 결론적으로 위의 예제는 총 2개의 검색을 수행됩니다.
header에는 index와 search_type, preference, routing 같은 정보들을 작성하며,
body에는 query, aggregations, from, size 같은 요청 쿼리를 작성합니다.
각 json을 개행으로 구분하기 때문에, body의 모양을 예쁘게 하겠다고 개행을 해버리면 MultiSearch API를 호출할 수 없습니다.
즉, 다음과 같이 작성하면 안됩니다.
# vi query.json
{"index" : "test"}
{ "query" : { "match_all" : {} }, "from" : 0, "size" : 10 }
만약 쿼리가 길어서 별도의 파일로 보관하여 유지보수를 용이하게 하고 싶다면 template을 사용할 수 있습니다.
자세한 사용법은 여기를 참고해주세요!
2) MutlSearch API 호출
여러 키워드를 검색하기 위한 json 파일을 준비했다면, 다음과 같이 curl 요청으로 API를 호출할 수 있습니다.
# curl -X GET 'localhost:9200/인덱스/_msearch?pretty' -H 'Content-Type: application/x-ndjson' --data-binary @query.json
인덱스 명시
특정 index에 대해서 MultiSearch API를 호출하려면 URI에 인덱스를 명시해주고, 모든 index에 대해 검색하려면 'localhost:9200/_msearch'만 작성하면 됩니다.
그런데 모든 index에 대해 검색하면 성능이 좋지 않으므로 json 파일 각 header에서 인덱스를 명시하는 것이 좋습니다.
_msearch
MultiSerach API를 호출하기 위해서는 _search가 아닌 _msearch입니다.
Content-Type
공식 문서에서는 application/x-ndjson으로 명시할 것을 권장합니다.
--data-binary
MultiSearch에서 json 파일로 검색하기 위해서는 -d가 옵션이 아닌 --data-binary 옵션으로 full name을 작성해줘야 에러가 발생안합니다.
3) response
MultiSearch API 호출 결과 응답은 다음과 같은 양식을 따릅니다.
{ "responses" : [ { 단일 검색 결과 }, {
단일 검색 결과
},
... ] }
- responses
- MutlSearch로 총 100개의 검색을 수행했다면, responses 하위에는 100개의 json이 있습니다.
- 각 json은 _search API로 단일 호출했을 때의 결과가 그대로 있다고 보시면 됩니다.
그런데 검색하는 키워드가 많을 수록 데이터의 양은 엄청 커질 것이라는 것을 예측할 수 있습니다.
따라서 query를 작성할 때 특정 필드만 보여주는 방법 등으로 결과 document를 가공할 필요가 있습니다.
대량으로 document를 조회하는 방법은 이와 같이 MultiSearch API를 사용하면 됩니다.
다음은 대량으로 document를 추가하는 방법인 Bulk API에 대해 알아보겠습니다.
2. Bulk API ( 링크 )
Bulk API로 document를 대량으로 추가하는 방법도 MultiSearch API와 유사합니다.
json 파일을 만들어서 header와 body를 작성한 후, API를 호출하면 됩니다.
1) json 파일 작성
지금까지 Bulk API로 document를 추가하는 방법에 대해서만 언급했지만, 사실은 Bulk API를 통해 document를 update, delete도 할 수 있습니다.
# vi query.json
{ "index" : {} } { "name" : "test_auto_generate_id" } { "index" : { "_id" : "1" } } { "name" : "name_create1" } { "create" : {"_id" : "2" } } { "name" : "name_create2" } { "update" : {"_id" : "2" } } { "doc" : { "name" : "name_update" } } { "delete" : { "_id" : "2" } }
- { "index" : {} } / { "name" : "test_auto_generate_id" }
- URL에 index와 type을 명시한 경우 header에 "index" : {} 만 명시해도 해당 index, type에 document가 추가됩니다.
- header에 _id를 명시하지 않아도 자동으로 _id 값이 생성됩니다.
- { "index" : { "_id" : "1" } } / { "name" : "name_create1" }
- _id 값을 부여해서 document를 추가하는 방법입니다.
- { "create" : {"_id" : "2" } } / { "name" : "name_create2" }
- header에 "index"가 아닌 "create"를 명시하여 document를 추가하는 방법입니다.
- { "update" : {"_id" : "2" } } / { "doc" : { "name" : "name_update" } }
- Bulk API로 document를 update 할 수도 있습니다.
- update를 하려면 body에 "doc" 필드를 명시해줘야 합니다.
- { "delete" : { "_id" : "2" } }
- Bulk API로 document를 delete 할 수도 있습니다.
- delete를 할 때 body는 작성할 필요가 없습니다.
2) Bulk API 호출
다음은 Bulk API를 호출하는 curl 요청입니다.
# curl -X POST 'localhost:9200/victolee/test/_bulk?pretty' -H 'Content-Type: application/x-ndjson' --data-binary @query.json
위 예제에서는 URI에 특정 index와 type을 명시해줬으며,
Content-Type도 MultiSearch API와 같이 application/x-ndjson으로 작성했고, --data-binary 옵션으로 json 파일을 넘겨줍니다.
Bulk API를 호출할 때 여러 작업 중 하나가 실패하더라도 Bulk API는 실패하지 않습니다.
즉, 어떤 이유로 어느 한 작업이 실패하더라도 나머지 작업은 계속 처리됩니다.
response에서 각 작업의 상태를 전송 순서와 동일하게 표시하므로 어떤 작업이 실패했는지 여부를 알 수 있습니다.
이상으로 대량으로 document를 추가/수정/삭제하는 Bulk API 그리고 대량으로 document를 조회하는 MultiSearch API에 대해 알아보았습니다.