2.X/1. Getting Started

1-06-5. Complex Core Field Types

drscg 2017. 9. 30. 20:32

Besides the simple scalar datatypes that we have mentioned, JSON also has null values, arrays, and objects, all of which are supported by Elasticsearch.

위에서 언급한 기본 데이터 type외에도, JSON은 null 값, 배열, 오브젝트도 가질 수 있다. Elasticsearch는 이들 모두를 지원한다.

Multivalue Fieldsedit

It is quite possible that we want our tag field to contain more than one tag. Instead of a single string, we could index an array of tags:

tag field가 하나 이상의 태그를 포함하는 것은 당연히 가능하다. 단일 string 대신에, 태그의 배열을 색인할 수 있다.

{ "tag": [ "search", "nosql" ]}

There is no special mapping required for arrays. Any field can contain zero, one, or more values, in the same way as a full-text field is analyzed to produce multiple terms.

배열에 필요한 특별한 mapping은 없다. field는 full-text field가 여러 단어로 분석되듯이, 아무것도 없거나, 하나 이상의 값을 포함할 수 있다.

By implication, this means that all the values of an array must be of the same datatype. You can’t mix dates with strings. If you create a new field by indexing an array, Elasticsearch will use the datatype of the first value in the array to determine the type of the new field.

즉, 암묵리에, 배열에 있는 모든 값들은 동일한 데이터 type이다. date를 string과 섞어 쓸 수 없다. 배열을 색인 하여 새로운 field를 생성하면, Elasticsearch는 배열에 있는 첫 번째 값의 데이터 type을, 새로운 field의 type 으로 결정한다.

Note

When you get a document back from Elasticsearch, any arrays will be in the same order as when you indexed the document. The _source field that you get back contains exactly the same JSON document that you indexed.

Elasticsearch에서 document를 가져올 때, 배열은 document를 색인할 때와 동일한 순서가 될 것이다. 가져온 _source field는 색인한 것과 정확히 동일한 JSON document를 포함하고 있다.

However, arrays are indexed—made searchable—as multivalue fields, which are unordered. At search time, you can’t refer to "the first element" or "the last element". Rather, think of an array as a bag of values.

그러나, 배열은 다중 값 field로, 순서 없이, 검색 가능하게 색인 되므로, 검색 시에 "첫 번째 요소", "마지막 요소"를 참조할 수 없다. 배열은 값의 bag 이라 생각하는 것이 낫다.

Empty Fieldsedit

Arrays can, of course, be empty. This is the equivalent of having zero values. In fact, there is no way of storing a null value in Lucene, so a field with a null value is also considered to be an empty field.

물론, 배열은 비어 있을 수 있다. 이는 zero 값을 가지는 것과 같다. 사실, Lucene에는 null 값을 저장할 수 있는 방법이 없다. 그래서 null 값을 가지는 field도 empty field로 간주된다.

These three fields would all be considered to be empty, and would not be indexed:

아래의 세 field는 모두 비어 있는 것으로 간주된다. 그래서 색인되지 않는다.

"null_value":               null,
"empty_array":              [],
"array_with_null_value":    [ null ]

Multilevel Objectsedit

The last native JSON datatype that we need to discuss is the object — known in other languages as a hash, hashmap, dictionary or associative array.

이야기해야 할 마지막 JSON 데이터 type은, 다른 language에서 hash, hashmap, dictionary, associative 배열이라고 알려진 오브젝트(object) 이다.

inner objects are often used to embed one entity or object inside another. For instance, instead of having fields called user_name and user_id inside our tweet document, we could write it as follows:

inner objects 는 하나의 요소 또는 다른 것 내부에 오브젝트를 포함하는데 사용된다. 예를 들면, tweetdocument 내부에 user_name 과 user_id field를 가지는 대신, 아래처럼 쓸 수 있다.

{
    "tweet":            "Elasticsearch is very flexible",
    "user": {
        "id":           "@johnsmith",
        "gender":       "male",
        "age":          26,
        "name": {
            "full":     "John Smith",
            "first":    "John",
            "last":     "Smith"
        }
    }
}

Mapping for Inner Objectsedit

Elasticsearch will detect new object fields dynamically and map them as type object, with each inner field listed under properties:

Elasticsearch가 동적으로 새로운 오브젝트를 발견하면, 각 inner field를 properties 아래에 나열하고, 그들을 object type으로 mapping한다.

{
  "gb": {
    "tweet": { 
      "properties": {
        "tweet":            { "type": "string" },
        "user": { 
          "type":             "object",
          "properties": {
            "id":           { "type": "string" },
            "gender":       { "type": "string" },
            "age":          { "type": "long"   },
            "name":   { 
              "type":         "object",
              "properties": {
                "full":     { "type": "string" },
                "first":    { "type": "string" },
                "last":     { "type": "string" }
              }
            }
          }
        }
      }
    }
  }
}

Root object

 

Inner objects

The mapping for the user and name fields has a similar structure to the mapping for the tweet type itself. In fact, the type mapping is just a special type of object mapping, which we refer to as theroot objectIt is just the same as any other object, except that it has some special top-level fields for document metadata, such as _source, and the _all field.

user 와 name field의 mapping은 tweet type 자체의 mapping과 유사한 구조를 가진다. 사실, typemapping은 root object 라 불리는, object mapping의 특별한 type이다. _source_all field 처럼, document metadata를 나타내는, 몇 개의 특별한 최상위 레벨 field를 제외하면, 다른 오브젝트와 같다.

How Inner Objects are Indexededit

Lucene doesn’t understand inner objects. A Lucene document consists of a flat list of key-value pairs. In order for Elasticsearch to index inner objects usefully, it converts our document into something like this:

Lucene은 inner 오브젝트를 이해하지 못한다. Lucene document는 key-value 쌍의 평평한 목록으로 구성되어 있다. Elasticsearch가 inner 오브젝트를 유효하게 색인 하기 위해, document를 아래처럼 바꾼다.

{
    "tweet":            [elasticsearch, flexible, very],
    "user.id":          [@johnsmith],
    "user.gender":      [male],
    "user.age":         [26],
    "user.name.full":   [john, smith],
    "user.name.first":  [john],
    "user.name.last":   [smith]
}

inner fields can be referred to by name (for example, first). To distinguish between two fields that have the same name, we can use the full path (for example, user.name.first) or even the typename plus the path (tweet.user.name.first).

inner field 는 이름(예. first)으로 참조될 수 있다. 동일한 이름을 가진 두 개의 field를 구분하기 위해, full path 를 사용할 수 있다.(예: user.name.first) 또는 type name까지 path에 더해서 (tweet.user.name.first)

Note

In the preceding simple flattened document, there is no field called user and no field called user.name. Lucene indexes only scalar or simple values, not complex data structures.

위의 단순히 평평한 document에서, user 나 user.name 이라 불리는 field는 없다. Lucene은 복잡한 데이터 구조가 아닌, scalar나 simple value만을 색인 한다.

Arrays of Inner Objectsedit

Finally, consider how an array containing inner objects would be indexed. Let’s say we have a followers array that looks like this:

마지막으로, inner 오브젝트를 포함하는 배열이 색인되는 방법을 알아보자. 아래처럼 followers 배열을 가졌다고 기정해 보자.

{
    "followers": [
        { "age": 35, "name": "Mary White"},
        { "age": 26, "name": "Alex Jones"},
        { "age": 19, "name": "Lisa Smith"}
    ]
}

This document will be flattened as we described previously, but the result will look like this:

이 document는 위에서 언급한 것처럼 평평하게 될 것이다. 그러나 결과는 아래와 같다.

{
    "followers.age":    [19, 26, 35],
    "followers.name":   [alex, jones, lisa, smith, mary, white]
}

The correlation between {age: 35} and {name: Mary White} has been lost as each multivalue field is just a bag of values, not an ordered array. This is sufficient for us to ask, "Is there a follower who is 26 years old?"

{age: 35} 와 {name: Mary White} 의 연관성은, 각 다중 값 field가 순서가 있는 배열이 아닌, 값의 주머니가 되면서 없어졌다. 이 질문은 답할 수 있을 것이다. "26세인 follower가 있나요?""

But we can’t get an accurate answer to this: "Is there a follower who is 26 years old and who is called Alex Jones?"

그러나, 이 질문은 정확한 답을 할 수 없다. "26세 이고 Alex Jones라 불리는 follower가 있나요?"

Correlated inner objects, which are able to answer queries like these, are called nested objects, and we cover them later, in Nested Objects.

이 같은 query에 답하려면, 연관된 inner 오브젝트는 nested 오브젝트라 불려야 한다. 나중에 Nested Objects에서 이야기 할 것이다.


'2.X > 1. Getting Started' 카테고리의 다른 글

1-06-3. Analysis and Analyzers  (0) 2017.09.30
1-06-4. Mapping  (0) 2017.09.30
1-07. Full-Body Search  (0) 2017.09.30
1-07-1. Empty Search  (0) 2017.09.30
1-07-2. Query DSL  (0) 2017.09.30