Skip to content

Latest commit

 

History

History
412 lines (344 loc) · 13.5 KB

File metadata and controls

412 lines (344 loc) · 13.5 KB

02. Elasticsearch Bulk & Mapping & Search

실습환경

  • Windows 10
  • Elasticsearch 7.10.2
  • Git Bash

<참고>

강의는 5.1.1 버전이며, 강의에서 진행한 실습 코드를 그대로 진행하여 document type이 _doc이 아닌 custom type입니다.

01. Elasticsearch Bulk (벌크)

한 번에 여러 데이터를 삽입하는 것을 Bulk 라고 하며, Elasticsearch에 Bulk 하는 방법에 대해 살펴보려 합니다.

Bulk 데이터 살펴보기

실습 전, Document Bulk 데이터인 classes.json을 확인해보면 아래와 같이 한 데이터가 두 줄로 구성되어 있는 것을 볼 수 있습니다.

{ "index" : { "_index" : "classes", "_type" : "class", "_id" : "1" } }
{"title" : "Machine Learning","Professor" : "Subin Kim","major" : "Computer Science","semester" : ["spring", "fall"],"student_count" : 100,"unit" : 3,"rating" : 5, "submit_date" : "2020-01-02", "school_location" : {"lat" : 36.00, "lon" : -120.00}}
  • 첫 번째 라인 : Meta Infomation
  • 두 번째 라인 : Document 데이터

파일의 맨 마지막 줄에는 \n(enter)가 반드시 추가되어야 합니다. 추가하지 않으면, The bulk request must be terminated by a newline [\\n] 에러가 발생합니다.

classes.json의 데이터와 같이 index를 통해 데이터를 생성하거나 기존의 데이터를 수정을 할 때는 두 줄로 데이터를 구성해야 합니다. 마찬가지로 생성을 위한 create나 수정을 위한 update를 사용할 때도 두 줄로 데이터를 구성해야 합니다. 삭제를 하는 delete를 사용할 때만 한 줄로 데이터를 구성합니다.

{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : { "_index" : "test", "_id" : "1" } }
{ "doc" : { "field2" : "value2" } }

Bulk 수행하기

Bulk를 위해 구성한 데이터 파일은 아래 명령어를 통해 Elasticsearch 내에 Bulk를 수행할 수 있습니다.

curl -X POST {elasticsearch address}/_bulk --data-binary @{파일명}.json -H'Content-Type:application/json'
# e.g.
curl -X POST http://localhost:9200/_bulk?pretty  --data-binary @classes.json -H 'Content-Type:application/json'

데이터가 제대로 들어갔는지 GET을 통해 조회해봅시다.

curl -X GET http://localhost:9200/classes/class/1?pretty

그러면 아래와 같이 데이터가 정상적으로 들어가있는 것을 확인할 수 있습니다.

{
  "_index" : "classes",
  "_type" : "class",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "title" : "Machine Learning",
    "Professor" : "Subin Kim",
    "major" : "Computer Science",
    "semester" : [
      "spring",
      "fall"
    ],
    "student_count" : 100,
    "unit" : 3,
    "rating" : 5,
    "submit_date" : "2020-01-02",
    "school_location" : {
      "lat" : 36.0,
      "lon" : -120.0
    }
  }
}

02. Elasticsearch Mapping (매핑)

Mapping 살펴보기

Mapping을 관계형 데이터베이스로 비유하면 Schema로 표현할 수 있습니다. 지금까지 진행했던 실습처럼 Mapping 없이 Elasticsearch의 데이터를 넣을 수 있으며, Mapping 정보를 강제하지 않습니다. Mapping을 직접 설정하지 않는 경우, Elasticsearch에서는 Json 데이터를 기반으로 타입을 Mapping해줍니다. 이를 Dynamic Mapping (다이나믹 매핑) 이라고 합니다.

Dynamic Mapping은 필드가 포함할 수 있는 가장 넓은 범위의 데이터 타입을 선택합니다. 예를 들어 age 필드 값은 0부터 100까지의 숫자가 들어간다고 할 때, int로도 충분하지만 Elasticsearch는 자연수 타입 중 가장 큰 long으로 타입을 지정합니다. 그리고 Json에서 사용하는 ISO8601 표준 날짜 형식의 데이터가 아닌 다른 포맷의 날짜는 text 타입으로 인식됩니다.

올바른 타입으로 설정하고 정확한 데이터를 Kibana 대시보드에 표출하고 분석하기 위해서는 Explict Mapping (명시적 매핑) 을 하는 것이 좋습니다. 지금부터 Explict Mapping에 대해 살펴볼 예정이며, 아래부터는 Explict Mapping을 Mapping이라고 표현하겠습니다.

Index 생성하기

Mapping 실습 진행 전, Bulk 실습 과정에서 생성된 classes 인덱스를 삭제해줍니다.

curl -X DELETE http://localhost:9200/classes?pretty

그 다음, classes 인덱스를 생성합니다.

curl -X PUT http://localhost:9200/classes?pretty

생성한 classes 인덱스를 GET으로 조회해봅시다.

curl -X GET http://localhost:9200/classes?pretty

그러면 아래와 같이 mapping 부분이 비어있는 것을 확인할 수 있습니다.

{
  "classes" : {
    "aliases" : { },
    "mappings" : { },
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "1",
        "provided_name" : "classes",
        "creation_date" : "1680496039096",
        "number_of_replicas" : "1",
        "uuid" : "dhteWlj-ReaKCcMpaRFDTg",
        "version" : {
          "created" : "7100299"
        }
      }
    }
  }
}

Mapping 수행하기

classesRating_mapping.json 파일에 미리 Mapping 할 정보를 추가한 다음, 아래 명령어를 통해 Mapping을 수행해봅시다.

curl -X PUT '{elasticsearch address}/{index name}/{index_type}/_mapping' -H 'Content-Type:application/json' -d @{파일명}.json
# e.g.
curl -X PUT 'http://localhost:9200/classes/class/_mapping?include_type_name=true&pretty' -H 'Content-Type:application/json' -d @classesRating_mapping.json

실습 명령어를 보면 include_type_name=true가 존재하는데, 이는 7.x 버전 공식 문서에 나온 것처럼 무형식 API를 사용하기 위해서는 추가주어야 하는 명령어입니다.

추가한 Mapping이 적용되었는지 확인하기 위해 classes 인덱스를 GET으로 조회해봅시다.

curl -X GET http://localhost:9200/classes?pretty

그러면 아래와 같이 Mapping이 정상 적용된 것을 볼 수 있습니다.

{
  "classes" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "major" : {
          "type" : "text"
        },
        "professor" : {
          "type" : "text"
        },
        "rating" : {
          "type" : "integer"
        },
        "school_location" : {
          "type" : "geo_point"
        },
        "semester" : {
          "type" : "text"
        },
        "student_count" : {
          "type" : "integer"
        },
        "submit_date" : {
          "type" : "date",
          "format" : "yyyy-MM-dd"
        },
        "title" : {
          "type" : "text"
        },
        "unit" : {
          "type" : "integer"
        }
      }
    },
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "1",
        "provided_name" : "classes",
        "creation_date" : "1680496039096",
        "number_of_replicas" : "1",
        "uuid" : "dhteWlj-ReaKCcMpaRFDTg",
        "version" : {
          "created" : "7100299"
        }
      }
    }
  }
}

이제 이전에 학습한 Bulk를 통해 데이터를 추가할 때, 정상적으로 추가되는지 실행해봅시다.

curl -X POST http://localhost:9200/_bulk?pretty  --data-binary @classes.json -H 'Content-Type:application/json'

데이터가 제대로 들어갔는지 GET을 통해 확인할 수 있습니다. (데이터는 위와 동일하게 표출되므로 여기서는 생략하겠습니다.)

curl -X GET http://localhost:9200/classes/class/1?pretty

03. Elasticsearch Search (검색)

실습 전 준비사항

Elasticsearch의 Search 기능에 대해 알아보기 전, 실습에 필요한 데이터를 Bulk 합니다.

curl -X POST http://localhost:9200/_bulk?pretty --data-binary @simple_basketball.json -H 'Content-Type:application/json'

simple_basketball.json은 아래의 데이터로 구성되어 있습니다.

{ "index" : { "_index" : "basketball", "_type" : "record", "_id" : "1" } }
{"team" : "Chicago Bulls","name" : "Subin Kim", "points" : 30,"rebounds" : 3,"assists" : 4, "submit_date" : "2023-04-03"}
{ "index" : { "_index" : "basketball", "_type" : "record", "_id" : "2" } }
{"team" : "Chicago Bulls","name" : "Subin Kim","points" : 20,"rebounds" : 5,"assists" : 8, "submit_date" : "2023-04-03"}

Search - Option X

먼저, 옵션 없이 Search 명령어를 사용하는 방법에 대해 알아봅시다.

curl -X GET {elasticsearch address}/{index name}/{document type}/_search
# e.g.
curl -X GET http://localhost:9200/basketball/record/_search?pretty

참고로 7.0 버전부터는 Document Type에 대한 개념이 사라져서 명령어 입력 시 document type에 대해 입력할 필요가 없습니다.

curl -X GET {elasticsearch address}/{index name}/_search

이렇게 옵션 없이 명령어를 입력하면 모든 결과를 출력합니다.

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "basketball",
        "_type" : "record",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "team" : "Chicago Bulls",
          "name" : "Subin Kim",
          "points" : 30,
          "rebounds" : 3,
          "assists" : 4,
          "submit_date" : "2023-03-20"
        }
      },
      {
        "_index" : "basketball",
        "_type" : "record",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "team" : "Chicago Bulls",
          "name" : "Subin Kim",
          "points" : 20,
          "rebounds" : 5,
          "assists" : 8,
          "submit_date" : "2023-04-03"
        }
      }
    ]
  }
}

Search - Querystring

Search 명령 URI 내에 QueryString을 추가하여 Search Option을 설정할 수 있습니다. 마찬가지로, 위에서 설명한 것처럼 7.0 버전부터는 document type에 대해 입력할 필요가 없습니다.

curl -X GET {elasticsearch address}/{index name}/{document type}/_search?q={value}
# e.g.
curl -X GET 'http://localhost:9200/basketball/record/_search?q=points:30&pretty'

실습 명령어를 실행해보면 points가 30인 document에 대해서만 출력하는 것을 확인할 수 있습니다.

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "basketball",
        "_type" : "record",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "team" : "Chicago Bulls",
          "name" : "Subin Kim",
          "points" : 30,
          "rebounds" : 3,
          "assists" : 4,
          "submit_date" : "2023-03-20"
        }
      }
    ]
  }
}

Search - QueryDSL

Search에는 Request Body에 Option을 넣어 실행하는 방법도 존재합니다. 위의 URI 내에 Optino을 추가하는 Querystring을 Request Body 내에 Option을 설정하는 QueryDSL로 변경하였습니다. 참고로, RequesgBody는 json 구조이기 때문에 {} 아닌 <<>>로 사용자 입력 값을 표시하였습니다.

curl -X GET '{elasticsearch address}/{index name}/{document type}/_search'  -H 'Content-Type: application/json' -d '
{
  "query": {
    "<<query>>" : {
      "field": <<value>>
    }
  }
}' 
# e.g.
curl -X GET 'http://localhost:9200/basketball/record/_search?pretty' -H 'Content-Type: application/json' -d '
{
    "query" : {
        "term" : {
            "points" : 30
        }
    }
}'

사용할 수 있는 Query는 여러 개가 존재하는데, 여기서는 term을 사용하여 실습을 진행했습니다. 다른 Query에 대해 알고 싶다면 공식문서를 참고하길 바랍니다.

본 게시글은 ELK 스택 (ElasticSearch, Logstash, Kibana) 으로 데이터 분석 강의를 참고하여 작성되었습니다.

상세한 내용이 궁금하시다면 강의 수강을 추천해 드립니다.