1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
|
[[mapping-object-type]]
=== Object Type
JSON documents are hierarchical in nature, allowing them to define inner
"objects" within the actual JSON. Elasticsearch completely understands
the nature of these inner objects and can map them easily, providing
query support for their inner fields. Because each document can have
objects with different fields each time, objects mapped this way are
known as "dynamic". Dynamic mapping is enabled by default. Let's take
the following JSON as an example:
[source,js]
--------------------------------------------------
{
"tweet" : {
"person" : {
"name" : {
"first_name" : "Shay",
"last_name" : "Banon"
},
"sid" : "12345"
},
"message" : "This is a tweet!"
}
}
--------------------------------------------------
The above shows an example where a tweet includes the actual `person`
details. A `person` is an object, with a `sid`, and a `name` object
which has `first_name` and `last_name`. It's important to note that
`tweet` is also an object, although it is a special
<<mapping-root-object-type,root object type>>
which allows for additional mapping definitions.
The following is an example of explicit mapping for the above JSON:
[source,js]
--------------------------------------------------
{
"tweet" : {
"properties" : {
"person" : {
"type" : "object",
"properties" : {
"name" : {
"properties" : {
"first_name" : {"type" : "string"},
"last_name" : {"type" : "string"}
}
},
"sid" : {"type" : "string", "index" : "not_analyzed"}
}
},
"message" : {"type" : "string"}
}
}
}
--------------------------------------------------
In order to mark a mapping of type `object`, set the `type` to object.
This is an optional step, since if there are `properties` defined for
it, it will automatically be identified as an `object` mapping.
[float]
==== properties
An object mapping can optionally define one or more properties using the
`properties` tag for a field. Each property can be either another
`object`, or one of the
<<mapping-core-types,core_types>>.
[float]
==== dynamic
One of the most important features of Elasticsearch is its ability to be
schema-less. This means that, in our example above, the `person` object
can be indexed later with a new property -- `age`, for example -- and it
will automatically be added to the mapping definitions. Same goes for
the `tweet` root object.
This feature is by default turned on, and it's the `dynamic` nature of
each object mapped. Each object mapped is automatically dynamic, though
it can be explicitly turned off:
[source,js]
--------------------------------------------------
{
"tweet" : {
"properties" : {
"person" : {
"type" : "object",
"properties" : {
"name" : {
"dynamic" : false,
"properties" : {
"first_name" : {"type" : "string"},
"last_name" : {"type" : "string"}
}
},
"sid" : {"type" : "string", "index" : "not_analyzed"}
}
},
"message" : {"type" : "string"}
}
}
}
--------------------------------------------------
In the above example, the `name` object mapped is not dynamic, meaning
that if, in the future, we try to index JSON with a `middle_name` within
the `name` object, it will get discarded and not added.
There is no performance overhead if an `object` is dynamic, the ability
to turn it off is provided as a safety mechanism so "malformed" objects
won't, by mistake, index data that we do not wish to be indexed.
If a dynamic object contains yet another inner `object`, it will be
automatically added to the index and mapped as well.
When processing dynamic new fields, their type is automatically derived.
For example, if it is a `number`, it will automatically be treated as
number <<mapping-core-types,core_type>>. Dynamic
fields default to their default attributes, for example, they are not
stored and they are always indexed.
Date fields are special since they are represented as a `string`. Date
fields are detected if they can be parsed as a date when they are first
introduced into the system. The set of date formats that are tested
against can be configured using the `dynamic_date_formats` on the root object,
which is explained later.
Note, once a field has been added, *its type can not change*. For
example, if we added age and its value is a number, then it can't be
treated as a string.
The `dynamic` parameter can also be set to `strict`, meaning that not
only new fields will not be introduced into the mapping, parsing
(indexing) docs with such new fields will fail.
[float]
==== enabled
The `enabled` flag allows to disable parsing and indexing a named object
completely. This is handy when a portion of the JSON document contains
arbitrary JSON which should not be indexed, nor added to the mapping.
For example:
[source,js]
--------------------------------------------------
{
"tweet" : {
"properties" : {
"person" : {
"type" : "object",
"properties" : {
"name" : {
"type" : "object",
"enabled" : false
},
"sid" : {"type" : "string", "index" : "not_analyzed"}
}
},
"message" : {"type" : "string"}
}
}
}
--------------------------------------------------
In the above, `name` and its content will not be indexed at all.
[float]
==== include_in_all
`include_in_all` can be set on the `object` type level. When set, it
propagates down to all the inner mapping defined within the `object`
that do no explicitly set it.
[float]
==== path
deprecated[1.0.0,Use <<copy-to,`copy_to`>> instead]
In the <<mapping-core-types,core_types>>
section, a field can have a `index_name` associated with it in order to
control the name of the field that will be stored within the index. When
that field exists within an object(s) that are not the root object, the
name of the field of the index can either include the full "path" to the
field with its `index_name`, or just the `index_name`. For example
(under mapping of _type_ `person`, removed the tweet type for clarity):
[source,js]
--------------------------------------------------
{
"person" : {
"properties" : {
"name1" : {
"type" : "object",
"path" : "just_name",
"properties" : {
"first1" : {"type" : "string"},
"last1" : {"type" : "string", "index_name" : "i_last_1"}
}
},
"name2" : {
"type" : "object",
"path" : "full",
"properties" : {
"first2" : {"type" : "string"},
"last2" : {"type" : "string", "index_name" : "i_last_2"}
}
}
}
}
}
--------------------------------------------------
In the above example, the `name1` and `name2` objects within the
`person` object have different combination of `path` and `index_name`.
The document fields that will be stored in the index as a result of that
are:
[cols="<,<",options="header",]
|=================================
|JSON Name |Document Field Name
|`name1`/`first1` |`first1`
|`name1`/`last1` |`i_last_1`
|`name2`/`first2` |`name2.first2`
|`name2`/`last2` |`name2.i_last_2`
|=================================
Note, when querying or using a field name in any of the APIs provided
(search, query, selective loading, ...), there is an automatic detection
from logical full path and into the `index_name` and vice versa. For
example, even though `name1`/`last1` defines that it is stored with
`just_name` and a different `index_name`, it can either be referred to
using `name1.last1` (logical name), or its actual indexed name of
`i_last_1`.
More over, where applicable, for example, in queries, the full path
including the type can be used such as `person.name.last1`, in this
case, both the actual indexed name will be resolved to match against the
index, and an automatic query filter will be added to only match
`person` types.
|