Spec-Zone.ru › Elasticsearch 8
›Руководство по Elasticsearch [8.17] ›Отображение ›Динамическое отображение

Динамические шаблоны

Динамические шаблоны предоставляют больший контроль над тем, как Elasticsearch отображает ваши данные, выходя за рамки правил динамического отображения полей по умолчанию. Вы активируете динамическое отображение, установив параметр dynamic в значение true или runtime. Затем вы можете использовать динамические шаблоны для определения пользовательских отображений, которые могут применяться к динамически добавляемым полям на основе условия соответствия:

  • match_mapping_type и unmatch_mapping_type работают с типом данных, распознанным Elasticsearch
  • match и unmatch используют шаблон для соответствия имени поля
  • path_match и path_unmatch работают с полным путём к полю
  • Если динамический шаблон не определяет match_mapping_type, match или path_match, он не будет сопоставляться ни с каким полем. Вы по-прежнему можете ссылаться на шаблон по имени в разделе dynamic_templates запроса массовой индексации.

В спецификации отображения используйте {name} и {dynamic_type} переменные шаблона в качестве заглушек.

Динамические отображения полей добавляются только тогда, когда поле содержит конкретное значение. Elasticsearch не добавляет динамическое отображение поля, когда поле содержит null или пустой массив. Если используется опция null_value в dynamic_template, она будет применена только после индексации первого документа с конкретным значением для поля.

Динамические шаблоны задаются как массив именованных объектов:

  "dynamic_templates": [
    {
      "my_template_name": { 
        ... match conditions ... 
        "mapping": { ... } 
      }
    },
    ...
  ]

Имя шаблона может быть любым строковым значением.

Условия соответствия могут включать любые из : match_mapping_type, match, match_pattern, unmatch, path_match, path_unmatch.

Отображение, которое должно использоваться для сопоставленного поля.

Проверка динамических шаблонов

Если предоставленное отображение содержит некорректный фрагмент отображения, возвращается ошибка валидации. Проверка происходит при применении динамического шаблона во время индексирования и, в большинстве случаев, при обновлении динамического шаблона. Предоставление некорректного фрагмента отображения может привести к тому, что обновление или проверка динамического шаблона завершатся неудачно в определённых условиях:

  • Если не был указан match_mapping_type, но шаблон действителен хотя бы для одного предопределённого типа отображения, фрагмент отображения считается корректным. Однако, ошибка валидации возвращается во время индексирования, если поле, соответствующее шаблону, проиндексировано как другой тип. Например, конфигурирование динамического шаблона без match_mapping_type считается корректным для типа string, но если поле, соответствующее динамическому шаблону, проиндексировано как long, то ошибка валидации возвращается во время индексирования. Рекомендуется настроить match_mapping_type до ожидаемого типа JSON или настроить требуемый type во фрагменте отображения.
  • Если используется заглушка {name} во фрагменте отображения, проверка пропускается при обновлении динамического шаблона. Это происходит потому, что имя поля неизвестно в этот момент. Вместо этого, проверка выполняется при применении шаблона во время индексирования.

Шаблоны обрабатываются в порядке — первый соответствующий шаблон побеждает. При добавлении новых динамических шаблонов через API обновления отображения все существующие шаблоны перезаписываются. Это позволяет переупорядочивать или удалять динамические шаблоны после их первоначального добавления.

Отображение полей во время выполнения в динамическом шаблоне

Если вы хотите, чтобы Elasticsearch динамически отображал новые поля определённого типа как поля во время выполнения, установите "dynamic":"runtime" в отображениях индекса. Эти поля не индексируются и загружаются из _source во время запроса.

В качестве альтернативы, вы можете использовать правила динамического отображения по умолчанию, а затем создать динамические шаблоны для отображения определённых полей как полей во время выполнения. Установите "dynamic":"true" в вашем отображении индекса, а затем создайте динамический шаблон для отображения новых полей определённого типа как полей во время выполнения.

Предположим, у вас есть данные, где каждое из полей начинается с ip_. Основываясь на правилах динамического отображения, Elasticsearch отображает любые string, которые проходят обнаружение numeric, как float или long. Однако, вы можете создать динамический шаблон, отображающий новые строки как поля во время выполнения типа ip.

Следующий запрос определяет динамический шаблон под названием strings_as_ip. Когда Elasticsearch обнаруживает новые поля string, соответствующие шаблону ip*, он отображает эти поля как поля во время выполнения типа ip. Поскольку поля ip не отображаются динамически, вы можете использовать этот шаблон с "dynamic":"true" или "dynamic":"runtime".

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "strings_as_ip": {
                    "match_mapping_type": "string",
                    "match": "ip*",
                    "runtime": {
                        "type": "ip"
                    }
                }
            }
        ]
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          strings_as_ip: {
            match_mapping_type: 'string',
            match: 'ip*',
            runtime: {
              type: 'ip'
            }
          }
        }
      ]
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        strings_as_ip: {
          match_mapping_type: "string",
          match: "ip*",
          runtime: {
            type: "ip",
          },
        },
      },
    ],
  },
});
console.log(response);
PUT my-index-000001/
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_ip": {
          "match_mapping_type": "string",
          "match": "ip*",
          "runtime": {
            "type": "ip"
          }
        }
      }
    ]
  }
}

См. данный пример для того, как использовать динамические шаблоны для отображения полей string как индексируемых полей или полей во время выполнения.

match_mapping_type и unmatch_mapping_type

Параметр match_mapping_type сопоставляет поля по типу данных, определённому парсером JSON, в то время как unmatch_mapping_type исключает поля на основе типа данных.

Поскольку JSON не различает long от integer или double от float, любое разобранное число с плавающей точкой считается типом данных JSON double, а любое разобранное целое число считается типом long.

При динамических сопоставлениях Elasticsearch всегда выбирает более широкий тип данных. Единственное исключение — float, который требует меньше места для хранения, чем double и достаточно точен для большинства приложений. Динамические поля не поддерживают float, поэтому "dynamic":"runtime" использует double.

Elasticsearch автоматически определяет следующие типы данных:

Тип данных Elasticsearch

Тип данных JSON

"dynamic":"true"

"dynamic":"runtime"

null

Поле не добавлено

Поле не добавлено

true или false

boolean

boolean

double

float

double

long

long

long

object

object

Поле не добавлено

array

Зависит от первого не-null значения в массиве

Зависит от первого не-null значения в массиве

string, прошедший детекцию дат

date

date

string, прошедший детекцию чисел

float или long

double или long

string, не прошедший детекцию date или детекцию numeric

text с подполем .keyword

keyword

Вы можете указать либо один тип данных, либо список типов данных для параметров match_mapping_type или unmatch_mapping_type. Также можно использовать символ подстановки (*) для параметра match_mapping_type, чтобы сопоставить все типы данных.

Например, если мы хотели сопоставить все целые поля как integer вместо long, а все поля string как text и keyword, мы могли бы использовать следующую шаблон:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "numeric_counts": {
                    "match_mapping_type": [
                        "long",
                        "double"
                    ],
                    "match": "count",
                    "mapping": {
                        "type": "{dynamic_type}",
                        "index": False
                    }
                }
            },
            {
                "integers": {
                    "match_mapping_type": "long",
                    "mapping": {
                        "type": "integer"
                    }
                }
            },
            {
                "strings": {
                    "match_mapping_type": "string",
                    "mapping": {
                        "type": "text",
                        "fields": {
                            "raw": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    }
                }
            },
            {
                "non_objects_keyword": {
                    "match_mapping_type": "*",
                    "unmatch_mapping_type": "object",
                    "mapping": {
                        "type": "keyword"
                    }
                }
            }
        ]
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    document={
        "my_integer": 5,
        "my_string": "Some string",
        "my_boolean": "false",
        "field": {
            "count": 4
        }
    },
)
print(resp1)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          numeric_counts: {
            match_mapping_type: [
              'long',
              'double'
            ],
            match: 'count',
            mapping: {
              type: '{dynamic_type}',
              index: false
            }
          }
        },
        {
          integers: {
            match_mapping_type: 'long',
            mapping: {
              type: 'integer'
            }
          }
        },
        {
          strings: {
            match_mapping_type: 'string',
            mapping: {
              type: 'text',
              fields: {
                raw: {
                  type: 'keyword',
                  ignore_above: 256
                }
              }
            }
          }
        },
        {
          non_objects_keyword: {
            match_mapping_type: '*',
            unmatch_mapping_type: 'object',
            mapping: {
              type: 'keyword'
            }
          }
        }
      ]
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    my_integer: 5,
    my_string: 'Some string',
    my_boolean: 'false',
    field: {
      count: 4
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        numeric_counts: {
          match_mapping_type: ["long", "double"],
          match: "count",
          mapping: {
            type: "{dynamic_type}",
            index: false,
          },
        },
      },
      {
        integers: {
          match_mapping_type: "long",
          mapping: {
            type: "integer",
          },
        },
      },
      {
        strings: {
          match_mapping_type: "string",
          mapping: {
            type: "text",
            fields: {
              raw: {
                type: "keyword",
                ignore_above: 256,
              },
            },
          },
        },
      },
      {
        non_objects_keyword: {
          match_mapping_type: "*",
          unmatch_mapping_type: "object",
          mapping: {
            type: "keyword",
          },
        },
      },
    ],
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  document: {
    my_integer: 5,
    my_string: "Some string",
    my_boolean: "false",
    field: {
      count: 4,
    },
  },
});
console.log(response1);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "numeric_counts": {
          "match_mapping_type": ["long", "double"],
          "match": "count",
          "mapping": {
            "type": "{dynamic_type}",
            "index": false
          }
        }
      },
      {
        "integers": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "integer"
          }
        }
      },
      {
        "strings": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "fields": {
              "raw": {
                "type":  "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      },
      {
        "non_objects_keyword": {
          "match_mapping_type": "*",
          "unmatch_mapping_type": "object",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

PUT my-index-000001/_doc/1
{
  "my_integer": 5, 
  "my_string": "Some string", 
  "my_boolean": "false", 
  "field": {"count": 4} 
}

Поле my_integer сопоставляется как integer.

Поле my_string сопоставляется как text с keyword множественным полем.

Поле my_boolean сопоставляется как keyword.

Поле field.count сопоставляется как long.

match и unmatch

Параметр match использует один или несколько шаблонов для сопоставления с именем поля, в то время как unmatch использует один или несколько шаблонов для исключения полей, сопоставленных с match.

Параметр match_pattern изменяет поведение параметра match для поддержки полного соответствия регулярным выражениям Java по имени поля, а не простым символам подстановки. Например:

  "match_pattern": "regex",
  "match": "^profit_\d+$"

Следующий пример сопоставляет все поля string, чьё имя начинается с long_ (кроме тех, которые оканчиваются на _text) и сопоставляет их как поля long:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "longs_as_strings": {
                    "match_mapping_type": "string",
                    "match": "long_*",
                    "unmatch": "*_text",
                    "mapping": {
                        "type": "long"
                    }
                }
            }
        ]
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    document={
        "long_num": "5",
        "long_text": "foo"
    },
)
print(resp1)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          longs_as_strings: {
            match_mapping_type: 'string',
            match: 'long_*',
            unmatch: '*_text',
            mapping: {
              type: 'long'
            }
          }
        }
      ]
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    long_num: '5',
    long_text: 'foo'
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        longs_as_strings: {
          match_mapping_type: "string",
          match: "long_*",
          unmatch: "*_text",
          mapping: {
            type: "long",
          },
        },
      },
    ],
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  document: {
    long_num: "5",
    long_text: "foo",
  },
});
console.log(response1);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "longs_as_strings": {
          "match_mapping_type": "string",
          "match":   "long_*",
          "unmatch": "*_text",
          "mapping": {
            "type": "long"
          }
        }
      }
    ]
  }
}

PUT my-index-000001/_doc/1
{
  "long_num": "5", 
  "long_text": "foo" 
}

Поле long_num сопоставляется как long.

Поле long_text использует стандартное сопоставление string.

Вы можете указать список шаблонов, используя JSON массив для полей match или unmatch.

Следующий пример сопоставляет все поля, чьё имя начинается с ip_ или оканчивается на _ip, за исключением полей, которые начинаются с one или оканчиваются на two, и сопоставляет их как поля ip:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "ip_fields": {
                    "match": [
                        "ip_*",
                        "*_ip"
                    ],
                    "unmatch": [
                        "one*",
                        "*two"
                    ],
                    "mapping": {
                        "type": "ip"
                    }
                }
            }
        ]
    },
)
print(resp)

resp1 = client.index(
    index="my-index",
    id="1",
    document={
        "one_ip": "will not match",
        "ip_two": "will not match",
        "three_ip": "12.12.12.12",
        "ip_four": "13.13.13.13"
    },
)
print(resp1)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          ip_fields: {
            match: [
              'ip_*',
              '*_ip'
            ],
            unmatch: [
              'one*',
              '*two'
            ],
            mapping: {
              type: 'ip'
            }
          }
        }
      ]
    }
  }
)
puts response

response = client.index(
  index: 'my-index',
  id: 1,
  body: {
    one_ip: 'will not match',
    ip_two: 'will not match',
    three_ip: '12.12.12.12',
    ip_four: '13.13.13.13'
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        ip_fields: {
          match: ["ip_*", "*_ip"],
          unmatch: ["one*", "*two"],
          mapping: {
            type: "ip",
          },
        },
      },
    ],
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index",
  id: 1,
  document: {
    one_ip: "will not match",
    ip_two: "will not match",
    three_ip: "12.12.12.12",
    ip_four: "13.13.13.13",
  },
});
console.log(response1);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "ip_fields": {
          "match":   ["ip_*", "*_ip"],
          "unmatch": ["one*", "*two"],
          "mapping": {
            "type": "ip"
          }
        }
      }
    ]
  }
}

PUT my-index/_doc/1
{
  "one_ip":   "will not match", 
  "ip_two":   "will not match", 
  "three_ip": "12.12.12.12", 
  "ip_four":  "13.13.13.13" 
}

Поле one_ip не сопоставлено, поэтому использует стандартное сопоставление text.

Поле ip_two не сопоставлено, поэтому использует стандартное сопоставление text.

Поле three_ip сопоставляется с типом ip.

Поле ip_four сопоставляется с типом ip.

path_match и path_unmatch

Параметры path_match и path_unmatch работают аналогично параметрам match и unmatch, но работают с полным составным именем поля, а не только с последним именем, например, some_object.*.some_field.

В этом примере значения любых полей в объекте name копируются в поле верхнего уровня full_name, за исключением поля middle:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "full_name": {
                    "path_match": "name.*",
                    "path_unmatch": "*.middle",
                    "mapping": {
                        "type": "text",
                        "copy_to": "full_name"
                    }
                }
            }
        ]
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    document={
        "name": {
            "first": "John",
            "middle": "Winston",
            "last": "Lennon"
        }
    },
)
print(resp1)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          full_name: {
            path_match: 'name.*',
            path_unmatch: '*.middle',
            mapping: {
              type: 'text',
              copy_to: 'full_name'
            }
          }
        }
      ]
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    name: {
      first: 'John',
      middle: 'Winston',
      last: 'Lennon'
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        full_name: {
          path_match: "name.*",
          path_unmatch: "*.middle",
          mapping: {
            type: "text",
            copy_to: "full_name",
          },
        },
      },
    ],
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  document: {
    name: {
      first: "John",
      middle: "Winston",
      last: "Lennon",
    },
  },
});
console.log(response1);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "full_name": {
          "path_match":   "name.*",
          "path_unmatch": "*.middle",
          "mapping": {
            "type":       "text",
            "copy_to":    "full_name"
          }
        }
      }
    ]
  }
}

PUT my-index-000001/_doc/1
{
  "name": {
    "first":  "John",
    "middle": "Winston",
    "last":   "Lennon"
  }
}

В следующем примере используется массив шаблонов для path_match и path_unmatch.

Значения любых полей в объекте name или объекте user.name копируются в поле верхнего уровня full_name, за исключением полей middle и midinitial:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "full_name": {
                    "path_match": [
                        "name.*",
                        "user.name.*"
                    ],
                    "path_unmatch": [
                        "*.middle",
                        "*.midinitial"
                    ],
                    "mapping": {
                        "type": "text",
                        "copy_to": "full_name"
                    }
                }
            }
        ]
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    document={
        "name": {
            "first": "John",
            "middle": "Winston",
            "last": "Lennon"
        }
    },
)
print(resp1)

resp2 = client.index(
    index="my-index-000001",
    id="2",
    document={
        "user": {
            "name": {
                "first": "Jane",
                "midinitial": "M",
                "last": "Salazar"
            }
        }
    },
)
print(resp2)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          full_name: {
            path_match: [
              'name.*',
              'user.name.*'
            ],
            path_unmatch: [
              '*.middle',
              '*.midinitial'
            ],
            mapping: {
              type: 'text',
              copy_to: 'full_name'
            }
          }
        }
      ]
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    name: {
      first: 'John',
      middle: 'Winston',
      last: 'Lennon'
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 2,
  body: {
    user: {
      name: {
        first: 'Jane',
        midinitial: 'M',
        last: 'Salazar'
      }
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        full_name: {
          path_match: ["name.*", "user.name.*"],
          path_unmatch: ["*.middle", "*.midinitial"],
          mapping: {
            type: "text",
            copy_to: "full_name",
          },
        },
      },
    ],
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  document: {
    name: {
      first: "John",
      middle: "Winston",
      last: "Lennon",
    },
  },
});
console.log(response1);

const response2 = await client.index({
  index: "my-index-000001",
  id: 2,
  document: {
    user: {
      name: {
        first: "Jane",
        midinitial: "M",
        last: "Salazar",
      },
    },
  },
});
console.log(response2);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "full_name": {
          "path_match":   ["name.*", "user.name.*"],
          "path_unmatch": ["*.middle", "*.midinitial"],
          "mapping": {
            "type":       "text",
            "copy_to":    "full_name"
          }
        }
      }
    ]
  }
}

PUT my-index-000001/_doc/1
{
  "name": {
    "first":  "John",
    "middle": "Winston",
    "last":   "Lennon"
  }
}

PUT my-index-000001/_doc/2
{
  "user": {
    "name": {
      "first":      "Jane",
      "midinitial": "M",
      "last":       "Salazar"
    }
  }
}

Обратите внимание, что параметры path_match и path_unmatch соответствуют путям объектов, помимо самих листовых полей. Например, индексирование следующего документа приведёт к ошибке, так как параметр path_match также соответствует объектному полю name.title, которое не может быть отображено как текст:

resp = client.index(
    index="my-index-000001",
    id="2",
    document={
        "name": {
            "first": "Paul",
            "last": "McCartney",
            "title": {
                "value": "Sir",
                "category": "order of chivalry"
            }
        }
    },
)
print(resp)
response = client.index(
  index: 'my-index-000001',
  id: 2,
  body: {
    name: {
      first: 'Paul',
      last: 'McCartney',
      title: {
        value: 'Sir',
        category: 'order of chivalry'
      }
    }
  }
)
puts response
const response = await client.index({
  index: "my-index-000001",
  id: 2,
  document: {
    name: {
      first: "Paul",
      last: "McCartney",
      title: {
        value: "Sir",
        category: "order of chivalry",
      },
    },
  },
});
console.log(response);
PUT my-index-000001/_doc/2
{
  "name": {
    "first":  "Paul",
    "last":   "McCartney",
    "title": {
      "value": "Sir",
      "category": "order of chivalry"
    }
  }
}

Переменные шаблона

Замените плацехолдеры {name} и {dynamic_type} в mapping именем поля и определённым динамическим типом. В следующем примере все строковые поля используют анализатор analyzer с тем же именем, что и поле, и отключает doc_values для всех полей, не являющихся строками:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "named_analyzers": {
                    "match_mapping_type": "string",
                    "match": "*",
                    "mapping": {
                        "type": "text",
                        "analyzer": "{name}"
                    }
                }
            },
            {
                "no_doc_values": {
                    "match_mapping_type": "*",
                    "mapping": {
                        "type": "{dynamic_type}",
                        "doc_values": False
                    }
                }
            }
        ]
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    document={
        "english": "Some English text",
        "count": 5
    },
)
print(resp1)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          named_analyzers: {
            match_mapping_type: 'string',
            match: '*',
            mapping: {
              type: 'text',
              analyzer: '{name}'
            }
          }
        },
        {
          no_doc_values: {
            match_mapping_type: '*',
            mapping: {
              type: '{dynamic_type}',
              doc_values: false
            }
          }
        }
      ]
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    english: 'Some English text',
    count: 5
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        named_analyzers: {
          match_mapping_type: "string",
          match: "*",
          mapping: {
            type: "text",
            analyzer: "{name}",
          },
        },
      },
      {
        no_doc_values: {
          match_mapping_type: "*",
          mapping: {
            type: "{dynamic_type}",
            doc_values: false,
          },
        },
      },
    ],
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  document: {
    english: "Some English text",
    count: 5,
  },
});
console.log(response1);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "named_analyzers": {
          "match_mapping_type": "string",
          "match": "*",
          "mapping": {
            "type": "text",
            "analyzer": "{name}"
          }
        }
      },
      {
        "no_doc_values": {
          "match_mapping_type":"*",
          "mapping": {
            "type": "{dynamic_type}",
            "doc_values": false
          }
        }
      }
    ]
  }
}

PUT my-index-000001/_doc/1
{
  "english": "Some English text", 
  "count":   5 
}

Поле english отображается как поле string с анализатором english.

Поле count отображается как поле long с отключённым doc_values.

Примеры динамических шаблонов

Ниже приведены примеры потенциально полезных динамических шаблонов:

Структурированный поиск

При установке "dynamic":"true" Elasticsearch отобразит строковые поля как поле text с подполем keyword. Если вы индексируете только структурированное содержимое и не заинтересованы в полнотекстовом поиске, вы можете настроить Elasticsearch на отображение полей только как keyword. Однако при поиске по таким полям необходимо использовать точно такое же значение, которое было проиндексировано.

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "strings_as_keywords": {
                    "match_mapping_type": "string",
                    "mapping": {
                        "type": "keyword"
                    }
                }
            }
        ]
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          strings_as_keywords: {
            match_mapping_type: 'string',
            mapping: {
              type: 'keyword'
            }
          }
        }
      ]
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        strings_as_keywords: {
          match_mapping_type: "string",
          mapping: {
            type: "keyword",
          },
        },
      },
    ],
  },
});
console.log(response);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

text-только отображения для строк

В отличие от предыдущего примера, если вы заинтересованы только в полнотекстовом поиске по строковым полям и не планируете использовать агрегации, сортировку или точные поиски, вы можете указать Elasticsearch на отображение строк как text:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "strings_as_text": {
                    "match_mapping_type": "string",
                    "mapping": {
                        "type": "text"
                    }
                }
            }
        ]
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          strings_as_text: {
            match_mapping_type: 'string',
            mapping: {
              type: 'text'
            }
          }
        }
      ]
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        strings_as_text: {
          match_mapping_type: "string",
          mapping: {
            type: "text",
          },
        },
      },
    ],
  },
});
console.log(response);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_text": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text"
          }
        }
      }
    ]
  }
}

В качестве альтернативы, вы можете создать динамический шаблон для отображения строковых полей как keyword полей в разделе времени выполнения отображения. При обнаружении Elasticsearch новых полей типа string, эти поля будут созданы как поля времени выполнения типа keyword.

Хотя поля string не будут проиндексированы, их значения хранятся в _source и могут использоваться в запросах поиска, агрегациях, фильтрации и сортировке.

Например, следующий запрос создаёт динамический шаблон для отображения полей string как полей времени выполнения типа keyword. Несмотря на то, что определение runtime пустое, новые поля string будут отображаться как поля времени выполнения keyword, основываясь на правилах динамического отображения, используемых Elasticsearch для добавления типов полей в отображение. Любое поле string, которое не проходит проверку дат или чисел, автоматически отображается как keyword:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "strings_as_keywords": {
                    "match_mapping_type": "string",
                    "runtime": {}
                }
            }
        ]
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          strings_as_keywords: {
            match_mapping_type: 'string',
            runtime: {}
          }
        }
      ]
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        strings_as_keywords: {
          match_mapping_type: "string",
          runtime: {},
        },
      },
    ],
  },
});
console.log(response);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "runtime": {}
        }
      }
    ]
  }
}

Вы индексируете простой документ:

resp = client.index(
    index="my-index-000001",
    id="1",
    document={
        "english": "Some English text",
        "count": 5
    },
)
print(resp)
response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    english: 'Some English text',
    count: 5
  }
)
puts response
const response = await client.index({
  index: "my-index-000001",
  id: 1,
  document: {
    english: "Some English text",
    count: 5,
  },
});
console.log(response);
PUT my-index-000001/_doc/1
{
  "english": "Some English text",
  "count":   5
}

При просмотре отображения вы увидите, что поле english является полем времени выполнения типа keyword:

resp = client.indices.get_mapping(
    index="my-index-000001",
)
print(resp)
response = client.indices.get_mapping(
  index: 'my-index-000001'
)
puts response
const response = await client.indices.getMapping({
  index: "my-index-000001",
});
console.log(response);
GET my-index-000001/_mapping
{
  "my-index-000001" : {
    "mappings" : {
      "dynamic_templates" : [
        {
          "strings_as_keywords" : {
            "match_mapping_type" : "string",
            "runtime" : { }
          }
        }
      ],
      "runtime" : {
        "english" : {
          "type" : "keyword"
        }
      },
      "properties" : {
        "count" : {
          "type" : "long"
        }
      }
    }
  }
}

Отключенные нормы

Нормы — это факторы ранжирования на этапе индексирования. Если вам не нужна оценка (например, если вы никогда не сортируете документы по оценке), вы можете отключить хранение этих факторов ранжирования в индексе, чтобы сэкономить место.

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "strings_as_keywords": {
                    "match_mapping_type": "string",
                    "mapping": {
                        "type": "text",
                        "norms": False,
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    }
                }
            }
        ]
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          strings_as_keywords: {
            match_mapping_type: 'string',
            mapping: {
              type: 'text',
              norms: false,
              fields: {
                keyword: {
                  type: 'keyword',
                  ignore_above: 256
                }
              }
            }
          }
        }
      ]
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        strings_as_keywords: {
          match_mapping_type: "string",
          mapping: {
            type: "text",
            norms: false,
            fields: {
              keyword: {
                type: "keyword",
                ignore_above: 256,
              },
            },
          },
        },
      },
    ],
  },
});
console.log(response);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    ]
  }
}

Подполе keyword в этом шаблоне присутствует для соответствия стандартным правилам динамического отображения. Конечно, если вам не нужны эти подполя, поскольку вам не нужен точный поиск или агрегирование по этому полю, вы можете его удалить, как описано в предыдущем разделе.

Временные ряды

При выполнении анализа временных рядов с Elasticsearch часто бывает много числовых полей, по которым вы часто выполняете агрегацию, но никогда не фильтруете. В таком случае вы можете отключить индексирование этих полей, чтобы сэкономить дисковое пространство и, возможно, ускорить индексирование:

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic_templates": [
            {
                "unindexed_longs": {
                    "match_mapping_type": "long",
                    "mapping": {
                        "type": "long",
                        "index": False
                    }
                }
            },
            {
                "unindexed_doubles": {
                    "match_mapping_type": "double",
                    "mapping": {
                        "type": "float",
                        "index": False
                    }
                }
            }
        ]
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic_templates: [
        {
          unindexed_longs: {
            match_mapping_type: 'long',
            mapping: {
              type: 'long',
              index: false
            }
          }
        },
        {
          unindexed_doubles: {
            match_mapping_type: 'double',
            mapping: {
              type: 'float',
              index: false
            }
          }
        }
      ]
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic_templates: [
      {
        unindexed_longs: {
          match_mapping_type: "long",
          mapping: {
            type: "long",
            index: false,
          },
        },
      },
      {
        unindexed_doubles: {
          match_mapping_type: "double",
          mapping: {
            type: "float",
            index: false,
          },
        },
      },
    ],
  },
});
console.log(response);
PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "unindexed_longs": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "long",
            "index": false
          }
        }
      },
      {
        "unindexed_doubles": {
          "match_mapping_type": "double",
          "mapping": {
            "type": "float", 
            "index": false
          }
        }
      }
    ]
  }
}

Как и при стандартных правилах динамического отображения, числа с плавающей точкой отображаются как типы `float`, что обычно достаточно точно, но требует в два раза меньше дискового пространства.

© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/dynamic-templates.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API