[ElasticSearch2.x] 매핑(Mapping)

1. 개요


날짜 필드를 날짜로 처리할 수 있도록 숫자 필드를 숫자로 처리하고, 문자열 필드를 전체 텍스트 (Full-text) 나 정확한 (Exact-value) 문자열 값으로 처리하기 위해서, Elasticsearch는 모든 필드에 어떤 데이터 형식이 포함되어 있는지 알아야 합니다.이러한 유형과 필드의 정보는 맵핑(mapping)에 저장됩니다.
색인에 있는 모든 문서에는 유형 (type) 이 있습니다.모든 유형은 자신의 맵핑(mapping)이나 패턴 정의(schema definition)를 가지고 있습니다.맵은 형식 (type) 의 필드, 각 필드의 데이터 형식, 그리고 필드가 Elasticsearch에 의해 처리되는 방식을 정의합니다. (A mapping defines the fields within a type, the data type for each field, and how the field should be handled by Elasticsearch).맵은 유형에 연결된 메타데이터를 설정하는 데도 사용됩니다.
예를 들어 다음 매핑:
"mppings":{
    "football-type": {
        "properties": {
            "country": {
                "index": "not_analyzed",
                "store": true,
                "type": "string"
            },
            "club": {
                "store": true,
                "type": "string"
            },
            "name": {
                "store": true,
                "type": "string"
            }
        }
    }
}

2. 핵심 필드 유형


Elasticsearch는 다음과 같은 간단한 필드 유형을 지원합니다.
유형
데이터 유형
String
string
Whole number
byte short integer long
Floating point
float double
Boolean
boolean
Date
date
새 필드를 포함하는 문서를 인덱스할 때, 이전에 없었던 필드를 인덱스하면, Elasticsearch는 JSON의 기본 데이터 형식을 바탕으로 동적 맵을 사용합니다.https://www.elastic.co/guide/en/elasticsearch/guide/current/dynamic-mapping.html) 다음 규칙을 사용하여 필드 유형을 추측합니다.
JsonType
FieldType
Boolean: true 또는 false
"boolean"
Whole number: 123
"long"
Floating point:123.45
"double"
String, valid date: "2017-05-04"
"date"
String: "foo bar"
"string"
참고:
이것은 인용부호가 있는 숫자를 색인한다면, 예를 들어 "123"은 "long"형식이 아니라string"형식으로 비추게 된다는 것을 의미한다.그러나 필드가 "long"형식으로 비추면 Elasticsearch는 문자열을 long으로 변환하려고 시도합니다. 강제 변환이 실패하면 이상이 발생합니다.
예를 들어 색인 아래 정보(이전에는 mapping이 없었습니다):
Map map = Maps.newHashMap();
map.put("name", "C ");
map.put("sex", true);
map.put("age", 31);
map.put("birthday", "1985-02-05");
map.put("club", " ");

매핑 결과:
{
    "properties": {
        "birthday": {
            "format": "strict_date_optional_time||epoch_millis",
            "type": "date"
        },
        "sex": {
            "type": "boolean"
        },
        "club": {
            "type": "string"
        },
        "name": {
            "type": "string"
        },
        "age": {
            "type": "long"
        }
    }
}

3. 매핑 보기


맵핑 API를 사용하여 Elasticsearch의 매핑을 볼 수 있습니다.
IndicesAdminClient indicesAdminClient = client.admin().indices();
GetMappingsRequestBuilder getMappingsRequestBuilder = indicesAdminClient.prepareGetMappings(index);
GetMappingsResponse response = getMappingsRequestBuilder.get();
//  
for(ObjectCursor<String> key : response.getMappings().keys()){
    ImmutableOpenMap<String, MappingMetaData> mapping = response.getMappings().get(key.value);
    for(ObjectCursor<String> key2 : mapping.keys()){
        try {
            logger.info("------------- {}", mapping.get(key2.value).sourceAsMap().toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

출력 결과:
14:45:26.453 [main] INFO  com.sjf.open.api.indexAPI.IndexAPI - ------------- {properties={age={type=long}, birthday={type=date, format=strict_date_optional_time||epoch_millis}, club={type=string}, name={type=string}, sex={type=boolean}}}

4. 사용자 정의 필드 매핑


대부분의 경우 기본 데이터 형식이 충족되지만, 특히 문자열 형식 필드를 사용자 정의할 수도 있습니다.사용자 정의 유형을 사용하면 몇 가지를 완성할 수 있습니다.
  • 전체 텍스트 (full text) 문자열 필드와 정확한 문자열 필드를 구분합니다.예를 들어 문자열'베이징'은 전체 문자열 필드가 기본적으로'북'과'경'두 단어로 나뉘지만 대부분의 경우 우리가 필요로 하는 것은 도시 이름이고 단어를 구분할 필요가 없기 때문에 이것은 정확한 문자열 필드이고 index 속성을'not_analyzed'로 설정해야 한다
  • 특정 언어의 분석기를 사용한다
  • 부분 일치 필드를 최적화합니다
  • 사용자 정의 날짜 형식을 지정합니다

  • 4.1 type


    맵에서 가장 중요한 필드 매개 변수는 type입니다.string 형식의 필드를 제외하고는 type을 제외한 다른 맵이 거의 필요하지 않을 수도 있습니다. (For fields other than string fields, you will seldom need to map anything other than type):
    {
        "number_of_clicks": {
            "type": "integer"
        }
    }

    string 형식의 필드는 기본적으로 전체 텍스트를 포함하는 것을 고려하여 색인 전에 분석기 분석을 거쳐야 하고, 이 필드에서 전체 텍스트 검색을 하기 전에 검색 문자열을 분석기 처리를 거쳐야 한다.

    4.2 index


    string 필드에서 가장 중요한 매개 변수는 index이고, 다른 하나는 analyzer에서 설명합니다.
    index 매개 변수는 문자열이 어떤 방식으로 인덱스되는지 제어합니다.다음과 같은 세 가지 방법이 있습니다.
    값지다
    설명
    analyzed
    먼저 이 문자열을 분석한 다음에 인덱스합니다. 다시 말하면 전문 형식으로 이 필드를 인덱스합니다.
    not_analyzed
    색인 이 필드는 색인될 수 있지만, 색인 내용은 지정한 값과 같습니다. 이 필드를 분석하지 않습니다.
    no
    이 필드를 인덱스하지 않습니다. 이 필드는 검색할 수 없습니다.
    문자열 형식 필드의 경우 index 기본값은 not_analyzed.필드를 정확하게 매핑하려면 not_ 로 설정해야 합니다.analyzed:
    {
        "tag": {
            "type":     "string",
            "index":    "not_analyzed"
        }
    }

    참고:
    다른 간단한 유형(long,double,date 등)도 index 파라미터를 받아들이지만 상응하는 값은 no와 not_analyzed, 그것들의 값은analyzed가 될 수 없습니다.

    4.3 analyzer


    index가analyzed인 문자열 필드에 대해analyzer 파라미터를 사용하여 어떤 분석기가 검색과 인덱스에 사용될지 지정합니다.기본적으로, Elasticsearch는 표준 분석기를 사용하지만, whitespace,simple,english 등 분석기를 지정할 수 있는 내장된 분석기를 지정할 수 있습니다.
    {
        "tweet": {
            "type":     "string",
            "analyzer": "english"
        }
    }

    5. 매핑 업데이트


    색인을 처음 만들 때 type에 맵을 지정할 수 있습니다. (You can specify the mapping for a type when you first create an index)그 다음에 새로운 형식에 맵을 추가하거나 기존 형식에 맵을 업데이트할 수 있습니다. (Alternatively, you can add the mapping for a new type (or update the mapping for an existing type) later.
    참고:
    기존 맵에 필드를 추가할 수 있지만, 이미 존재하는 필드 맵을 수정할 수 없습니다. (Although you can add to an existing mapping, you can't change existing field mappings)만약 한 필드의 맵이 이미 존재한다면, 이것은 그 필드의 데이터가 인덱스되었다는 것을 의미할 수 있습니다.필드 맵을 바꾸면, 인덱스된 데이터가 오류가 발생할 수 있으며, 정확하게 검색할 수 없습니다.
    새 필드를 추가하기 위해 맵을 업데이트할 수 있지만, 기존 필드의 index 속성을analyzed에서 not_로 변경할 수 없습니다.analyzed.
    다음 코드를 사용하여 맵을 설정할 때 먼저 빈 색인을 만듭니다.
    // mapping
    XContentBuilder mappingBuilder;
    try {
        mappingBuilder = XContentFactory.jsonBuilder()
            .startObject()
            .startObject(type)
            .startObject("properties")
                .startObject("name").field("type", "string").field("store", "yes").endObject()
                .startObject("sex").field("type", "string").field("store", "yes").endObject()
                .startObject("college").field("type", "string").field("store", "yes").endObject()
                .startObject("age").field("type", "long").field("store", "yes").endObject()
                .startObject("school").field("type", "string").field("store", "yes").field("index", "not_analyzed").endObject()
            .endObject()
            .endObject()
            .endObject();
    } catch (Exception e) {
        logger.error("--------- putIndexMapping   mapping  :", e);
        return false;
    }
    IndicesAdminClient indicesAdminClient = client.admin().indices();
    PutMappingRequestBuilder putMappingRequestBuilder = indicesAdminClient.preparePutMapping(index);
    putMappingRequestBuilder.setType(type);
    putMappingRequestBuilder.setSource(mappingBuilder);
    //  
    PutMappingResponse response = putMappingRequestBuilder.get();

    결과 생성:
    "mappings":{
        "test-type": {
            "properties": {
                "college": {
                    "store": true,
                    "type": "string"
                },
                "school": {
                    "index": "not_analyzed",
                    "store": true,
                    "type": "string"
                },
                "sex": {
                    "store": true,
                    "type": "string"
                },
                "name": {
                    "store": true,
                    "type": "string"
                },
                "age": {
                    "store": true,
                    "type": "long"
                }
            }
        }
    }

    다음에 분석기를 추가해서english의 필드를 위에 비추면 새로운 필드가 위에 존재하는 비추기에 통합됩니다.
    // mapping
            XContentBuilder mappingBuilder;
            try {
                mappingBuilder = XContentFactory.jsonBuilder()
                        .startObject()
                        .startObject(type)
                        .startObject("properties")
                        .startObject("club").field("type", "string").field("index", "analyzed").field("analyzer", "english").endObject()
                        .endObject()
                        .endObject()
                        .endObject();
            } catch (Exception e) {
                logger.error("--------- putIndexMapping   mapping  :", e);
                return false;
            }

    결과 생성:
    "mappings":{
        "test-type": {
            "properties": {
                "college": {
                    "store": true,
                    "type": "string"
                },
                "school": {
                    "index": "not_analyzed",
                    "store": true,
                    "type": "string"
                },
                "sex": {
                    "store": true,
                    "type": "string"
                },
                "club": {
                    "analyzer": "english",
                    "type": "string"
                },
                "name": {
                    "store": true,
                    "type": "string"
                },
                "age": {
                    "store": true,
                    "type": "long"
                }
            }
        }
    }

    참조:https://www.elastic.co/guide/en/elasticsearch/guide/current/mapping-intro.html#core-fields

    좋은 웹페이지 즐겨찾기