Elasticsearch
Разница между индексами и типами
Поиск…
замечания
Легко видеть type s как таблицу в базе данных SQL, где index - это база данных SQL. Однако это не очень хороший подход к type s.
Все о типах
Фактически, типы - это буквально только поле метаданных, добавленное в каждый документ _type : _type . В приведенных выше примерах создаются два типа: my_type и my_other_type . Это означает, что каждый документ, связанный с типами, имеет дополнительное поле, автоматически определяемое как "_type": "my_type" ; это индексируется с документом, что делает его полем поиска или фильтрации , но оно не влияет на сам исходный документ, поэтому вашему приложению не нужно беспокоиться об этом.
Все типы живут в одном и том же индексе и, следовательно, в тех же коллективных осколках индекса. Даже на уровне диска они живут в одних и тех же файлах. Единственное разделение, создающее второй тип, является логичным. Каждый тип, независимо от того, является он уникальным или нет, должен существовать в сопоставлениях, и все эти сопоставления должны существовать в вашем состоянии кластера. Это поглощает память, и, если каждый тип обновляется динамически, он увеличивает производительность при изменении сопоставлений.
Таким образом, лучше всего определить только один тип, если вам действительно не нужны другие типы. Обычно встречаются сценарии, в которых желательны несколько типов. Например, представьте, что у вас был автомобильный указатель. Возможно, вам будет полезно разбить его несколькими типами:
- БМВ
- гнаться
- Хонда
- мазда
- мерседес
- ниссан
- Range Rover
- Тойота
- ...
Таким образом, вы можете искать все автомобили или ограничивать их производителем по требованию. Разница между этими двумя поисками также проста:
GET /cars/_search
а также
GET /cars/bmw/_search
Что не очевидно для новых пользователей Elasticsearch, так это то, что вторая форма является специализацией первой формы. Он буквально переписывается:
GET /cars/_search
{
"query": {
"bool": {
"filter": [
{
"term" : {
"_type": "bmw"
}
}
]
}
}
}
Он просто отфильтровывает любой документ, который не был проиндексирован в поле _type , значение которого было bmw . Поскольку каждый документ индексируется с его типом в качестве поля _type , это служит довольно простым фильтром. Если фактический поиск был предоставлен в любом примере, тогда фильтр будет добавлен к полному поиску, если это необходимо.
Таким образом, если типы идентичны, гораздо лучше поставлять один тип (например, manufacturer в этом примере) и эффективно игнорировать его. Затем в каждом документе явно укажите поле под названием make или другое имя, которое вы предпочитаете, и вручную фильтруйте его, когда вы хотите его ограничить. Это уменьшит размер ваших сопоставлений до 1/n где n - количество отдельных типов. Он добавляет другое поле к каждому документу в пользу упрощенного сопоставления.
В Elasticsearch 1.x и 2.x такое поле должно быть определено как
PUT /cars
{
"manufacturer": { <1>
"properties": {
"make": { <2>
"type": "string",
"index": "not_analyzed"
}
}
}
}
- Имя произвольное.
- Имя произвольное, и оно может совпадать с именем типа, если вы тоже этого хотели.
В Elasticsearch 5.x вышеупомянутое все равно будет работать (оно устарело), но лучший способ - использовать:
PUT /cars
{
"manufacturer": { <1>
"properties": {
"make": { <2>
"type": "keyword"
}
}
}
}
- Имя произвольное.
- Имя произвольное, и оно может совпадать с именем типа, если вы тоже этого хотели.
Типы должны использоваться экономно в пределах ваших индексов, потому что они раздувают сопоставления индексов, как правило, без особых преимуществ. У вас должен быть хотя бы один, но нет ничего, что говорит, что у вас должно быть больше одного.
Общие вопросы
- Что делать, если у меня есть два (или более) типа, которые в основном идентичны, но которые имеют несколько уникальных полей для каждого типа?
На уровне индекса нет разницы между одним типом, который используется с несколькими полями, которые редко используются, и между несколькими типами, которые разделяют кучу не разреженных полей с несколькими не разделяемыми (что означает, что другой тип никогда не использует поле (ы)).
Сказано иначе: редко используемое поле разрежено по индексу независимо от типов . Разделение не приносит пользу - или действительно больно - индекс только потому, что он определен в отдельном типе.
Вы должны просто объединить эти типы и добавить отдельное поле типа.
- Почему отдельные типы должны точно определять поля точно так же?
Поскольку каждое поле действительно определено только один раз на уровне Lucene, независимо от количества типов. Тот факт, что типы существуют вообще, является особенностью Elasticsearch, и это только логическое разделение.
- Могу ли я определить отдельные типы с одинаковым полем, определенным по-разному?
Нет. Если вам удастся найти способ сделать это в ES 2.x или новее, тогда вы должны открыть отчет об ошибке . Как отмечалось в предыдущем вопросе, Луцен видит их всех как одно поле, поэтому нет возможности сделать эту работу надлежащим образом.
ES 1.x оставил это как неявное требование, которое позволило пользователям создавать условия, при которых одно отображение осколков в индексе фактически отличалось от другого осколка в том же индексе. Это было фактически условием гонки, и это могло привести к неожиданным проблемам.
Исключения из правила
- Родительские / дочерние документы требуют использования отдельных типов в одном и том же индексе.
- Родитель живет одним типом.
- Ребенок живет в отдельном типе (но каждый ребенок живет в том же осколке, что и его родитель).
- Чрезвычайно нишевые случаи использования, когда создание тонны индексов нежелательно, а влияние разреженных полей предпочтительнее альтернативы.
- Например, плагин мониторинга Elasticsearch, Marvel (1.x и 2.x) или X-Pack Monitoring (5.x +), контролирует сам Elasticsearch для изменений в кластере, узлах, индексах, конкретных индексах (уровне индекса), и даже осколки. Он может создавать 5 + индексов каждый день, чтобы изолировать те документы, которые имеют уникальные сопоставления, или может пойти против лучших практик, чтобы уменьшить нагрузку на кластер, разделив индекс (обратите внимание: количество определенных сопоставлений фактически одинаково, но количество созданных индексов уменьшается от
nдо 1). - Это расширенный сценарий, но вы должны учитывать общие определения полей для разных типов!
- Например, плагин мониторинга Elasticsearch, Marvel (1.x и 2.x) или X-Pack Monitoring (5.x +), контролирует сам Elasticsearch для изменений в кластере, узлах, индексах, конкретных индексах (уровне индекса), и даже осколки. Он может создавать 5 + индексов каждый день, чтобы изолировать те документы, которые имеют уникальные сопоставления, или может пойти против лучших практик, чтобы уменьшить нагрузку на кластер, разделив индекс (обратите внимание: количество определенных сопоставлений фактически одинаково, но количество созданных индексов уменьшается от
Явное создание индекса с типом
В примере используется базовый HTTP, который легко преобразуется в cURL и другие HTTP-приложения. Они также соответствуют синтаксису Sense , который будет переименован в Console в Kibana 5.0.
Примечание. В примере добавляется <#> чтобы привлечь внимание к частям. Их следует удалить, если вы его скопируете!
PUT /my_index <1>
{
"mappings": {
"my_type": { <2>
"properties": {
"field1": {
"type": "long"
},
"field2": {
"type": "integer"
},
"object1": {
"type": "object",
"properties": {
"field1" : {
"type": "float"
}
}
}
}
}
},
"my_other_type": {
"properties": {
"field1": {
"type": "long" <3>
},
"field3": { <4>
"type": "double"
}
}
}
}
- Это создает
indexиспользуя конечную точку создания индекса. - Это создает
type. - Общие поля
types внутри одного и того жеindexдолжны иметь одно и то же определение! ES 1.x не строго соблюдал это поведение, но это было неявное требование. ES 2.x и выше строго соблюдают это поведение. - Уникальные поля
types в порядке.
Индексы (или индексы) содержат типы. Типы - удобный механизм для разделения документов, но они требуют, чтобы вы определяли - либо динамически / автоматически, либо явно - сопоставление для каждого используемого вами типа. Если вы определяете 15 типов в индексе, то у вас есть 15 уникальных сопоставлений.
См. Замечания для получения более подробной информации об этой концепции и почему вы можете или не хотите использовать типы.
Динамическое создание индекса с типом
В примере используется базовый HTTP, который легко преобразуется в cURL и другие HTTP-приложения. Они также соответствуют синтаксису Sense , который будет переименован в Console в Kibana 5.0.
Примечание. В примере добавляется <#> чтобы привлечь внимание к частям. Их следует удалить, если вы его скопируете!
DELETE /my_index <1>
PUT /my_index/my_type/abc123 <2>
{
"field1" : 1234, <3>
"field2" : 456,
"object1" : {
"field1" : 7.8 <4>
}
}
- Если он уже существует (из-за более раннего примера), удалите индекс.
- Индексируйте документ в индекс
my_indexс типом,my_typeи IDabc123(может быть числовым, но это всегда строка).- По умолчанию динамическое создание индекса включается простым индексированием документа. Это отлично подходит для сред разработки, но это не обязательно хорошо для производственных сред.
- Это поле является целым числом, поэтому при первом просмотре его необходимо сопоставить. Elasticsearch всегда принимает самый широкий тип для любого входящего типа, поэтому он будет отображаться как
longа неintegerилиshort(оба из которых могут содержать1234и456). - То же самое верно и для этого поля. Он будет отображаться как
doubleа не какfloatкак вы, возможно, захотите.
Этот динамически созданный индекс и тип грубо соответствуют сопоставлению, определенному в первом примере. Однако очень важно понять, как <3> и <4> влияют на автоматически определенные сопоставления.
Вы могли бы следовать этому, добавив еще один тип динамически к одному и тому же индексу:
PUT /my_index/my_other_type/abc123 <1>
{
"field1": 91, <2>
"field3": 4.567
}
- Тип является единственным отличием от вышеуказанного документа. Идентификатор тот же, и все в порядке! Это не имеет никакого отношения к другим
abc123кроме того, что это происходит с тем же индексом. -
field1уже существует в индексе, поэтому он должен быть тем же типом поля, что и в других типах. Отказ от значения, который был строкой или не целой, потерпел бы неудачу (например,"field1": "this is some text"или"field1": 123.0).
Это будет динамически создавать сопоставления для my_other_type в одном и том же индексе my_index .
Примечание. Всегда быстрее определять сопоставления, вместо того, чтобы Elasticsearch динамически выполнял его во время индекса.
Конечный результат индексации обоих документов будет аналогичен первому примеру, но типы полей будут разными и, следовательно, немного расточительными:
GET /my_index/_mappings <1>
{
"mappings": {
"my_type": { <2>
"properties": {
"field1": {
"type": "long"
},
"field2": {
"type": "long" <3>
},
"object1": {
"type": "object",
"properties": {
"field1" : {
"type": "double" <4>
}
}
}
}
}
},
"my_other_type": { <5>
"properties": {
"field1": {
"type": "long"
},
"field3": {
"type": "double"
}
}
}
}
- Это использует
_mappingsточку_mappingsчтобы получить сопоставления из созданного нами индекса. - Мы динамически создали
my_typeна первом этапе этого примера. -
field2теперьlongа неintegerпотому что мы не определяли его заранее. Это может оказаться расточительным в дисковой памяти. -
object1.field1теперь являетсяdoubleпо той же причине, что и # 3 с теми же последствиями, что и # 3.- Технически,
longможет быть сжат во многих случаях. Однакоdoubleнельзя сжать из-за того, что он является числом с плавающей запятой.
- Технически,
- Мы также динамически создали
my_other_typeна втором этапе этого примера. Его сопоставление происходит одинаково, потому что мы уже использовалиlongиdouble.- Помните, что
field1должно соответствовать определению изmy_type(и оно). -
field3уникально для этого типа, поэтому оно не имеет такого ограничения.
- Помните, что