Spec-Zone.ru › Elasticsearch 7
›Elasticsearch Guide [7.17] ›Скрипты

Доступ к полям документа и специальным переменным

В зависимости от места использования скрипта, он будет иметь доступ к определенным специальным переменным и полям документа.

Скрипты обновления

Скрипт, используемый в API обновления, обновления по запросу или переиндексации, будет иметь доступ к переменной ctx, которая предоставляет:

ctx._source

Доступ к полю документа _source.

ctx.op

Операцию, которая должна быть применена к документу: index или delete.

ctx._index и т.д.

Доступ к метаданным документа, некоторые из которых могут быть только для чтения.

Скрипты поиска и агрегаций

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

Значения полей можно получить из скрипта с помощью doc-значений, поля _source или сохранённых полей, каждое из которых поясняется ниже.

Доступ к оценке релевантности документа в скрипте

Скрипты, используемые в function_score запросе, в сортировке на основе скриптов или в агрегациях, имеют доступ к переменной _score, которая представляет текущую оценку релевантности документа.

Вот пример использования скрипта в function_score запросе для изменения _score релевантности каждого документа:

PUT my-index-000001/_doc/1?refresh
{
  "text": "quick brown fox",
  "popularity": 1
}

PUT my-index-000001/_doc/2?refresh
{
  "text": "quick fox",
  "popularity": 5
}

GET my-index-000001/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "text": "quick brown fox"
        }
      },
      "script_score": {
        "script": {
          "lang": "expression",
          "source": "_score * doc['popularity']"
        }
      }
    }
  }
}

Doc-значения

Наиболее быстрый и эффективный способ доступа к значению поля из скрипта — использование синтаксиса doc['field_name'], который извлекает значение поля из doc-значений. Doc-значения — это хранилище значений полей в столбцах, включённое по умолчанию для всех полей, за исключением text полей.

PUT my-index-000001/_doc/1?refresh
{
  "cost_price": 100
}

GET my-index-000001/_search
{
  "script_fields": {
    "sales_price": {
      "script": {
        "lang":   "expression",
        "source": "doc['cost_price'] * markup",
        "params": {
          "markup": 0.2
        }
      }
    }
  }
}

Doc-значения могут возвращать только "простые" значения полей, такие как числа, даты, гео-точки, термины и т.д., или массивы этих значений, если поле многозначное. Они не могут возвращать JSON-объекты.

Отсутствующие поля

doc['field'] вызовет ошибку, если field отсутствует в схеме. В painless можно сначала проверить наличие поля с помощью doc.containsKey('field'), чтобы защитить доступ к карте doc. К сожалению, нет способа проверить существование поля в схеме в скрипте expression.

Doc-значения и поля text

Синтаксис doc['field'] также можно использовать для text полей, если fielddata включён, но ОСТОРОЖНО: включение fielddata для text поля требует загрузки всех терминов в кучу JVM, что может быть очень дорого как с точки зрения памяти, так и процессора. Редко имеет смысл обращаться к text полям из скриптов.

Поле документа _source

К полю документа _source можно получить доступ с помощью синтаксиса _source.field_name. Поле _source загружается как карта карт, поэтому к свойствам внутри полей объектов можно получить доступ, например, как _source.name.first.

Предпочитайте doc-значения полю _source

Доступ к полю _source намного медленнее, чем использование doc-значений. Поле _source оптимизировано для возврата нескольких полей на результат, в то время как doc-значения оптимизированы для доступа к значению определённого поля во многих документах.

Имеет смысл использовать _source при генерации поля скрипта для десяти лучших результатов поиска, но в других случаях поиска и агрегаций всегда предпочитайте использование doc-значений.

Например:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "first_name": {
        "type": "text"
      },
      "last_name": {
        "type": "text"
      }
    }
  }
}

PUT my-index-000001/_doc/1?refresh
{
  "first_name": "Barry",
  "last_name": "White"
}

GET my-index-000001/_search
{
  "script_fields": {
    "full_name": {
      "script": {
        "lang": "painless",
        "source": "params._source.first_name + ' ' + params._source.last_name"
      }
    }
  }
}

Сохранённые поля

Сохранённые поля — поля, явно помеченные как "store": true в схеме, — можно получить с помощью синтаксиса _fields['field_name'].value или _fields['field_name']:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "full_name": {
        "type": "text",
        "store": true
      },
      "title": {
        "type": "text",
        "store": true
      }
    }
  }
}

PUT my-index-000001/_doc/1?refresh
{
  "full_name": "Alice Ball",
  "title": "Professor"
}

GET my-index-000001/_search
{
  "script_fields": {
    "name_with_title": {
      "script": {
        "lang": "painless",
        "source": "params._fields['title'].value + ' ' + params._fields['full_name'].value"
      }
    }
  }
}

Сохраненные vs _source

Поле _source — это просто специальное сохранённое поле, поэтому производительность похожа на другие сохранённые поля. Поле _source предоставляет доступ к исходному телу документа, которое было проиндексировано (включая возможность отличать null значения от пустых полей, массивов одиночных значений от обычных скаляров и т.д.).

Единственный случай, когда имеет смысл использовать сохранённые поля вместо поля _source, — это когда поле _source очень большое, и доступ к нескольким небольшим сохранённым полям оказывается менее затратным, чем к полному полю _source.

© 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/7.17/modules-scripting-fields.html

Spec-Zone.ru

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