Spec-Zone.ru › Elasticsearch 8
›Elasticsearch Руководство [8.17] ›Картирование ›Поля в реальном времени

Получение поля в реальном времени

Используйте параметр fields для API _search, чтобы получить значения полей в реальном времени. Поля в реальном времени не отображаются в _source, но API fields работает для всех полей, даже тех, которые не были отправлены в составе исходного запроса _source.

Определение поля в реальном времени для расчета дня недели

Например, следующий запрос добавляет поле в реальном времени, названное day_of_week. Поле в реальном времени включает скрипт, который рассчитывает день недели на основе значения поля @timestamp. Мы включим "dynamic":"runtime" в запрос, чтобы новые поля добавлялись в схему как поля в реальном времени.

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic": "runtime",
        "runtime": {
            "day_of_week": {
                "type": "keyword",
                "script": {
                    "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
                }
            }
        },
        "properties": {
            "@timestamp": {
                "type": "date"
            }
        }
    },
)
print(resp)
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic: "runtime",
    runtime: {
      day_of_week: {
        type: "keyword",
        script: {
          source:
            "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))",
        },
      },
    },
    properties: {
      "@timestamp": {
        type: "date",
      },
    },
  },
});
console.log(response);
PUT my-index-000001/
{
  "mappings": {
    "dynamic": "runtime",
    "runtime": {
      "day_of_week": {
        "type": "keyword",
        "script": {
          "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
        }
      }
    },
    "properties": {
      "@timestamp": {"type": "date"}
    }
  }
}

Обработка данных

Давайте обработаем пример данных, что приведет к индексированию двух полей: @timestamp и message.

resp = client.bulk(
    index="my-index-000001",
    refresh=True,
    operations=[
        {
            "index": {}
        },
        {
            "@timestamp": "2020-06-21T15:00:01-05:00",
            "message": "211.11.9.0 - - [2020-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-06-21T15:00:01-05:00",
            "message": "211.11.9.0 - - [2020-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:30:17-05:00",
            "message": "40.135.0.0 - - [2020-04-30T14:30:17-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:30:53-05:00",
            "message": "232.0.0.0 - - [2020-04-30T14:30:53-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:31:12-05:00",
            "message": "26.1.0.0 - - [2020-04-30T14:31:12-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:31:19-05:00",
            "message": "247.37.0.0 - - [2020-04-30T14:31:19-05:00] \"GET /french/splash_inet.html HTTP/1.0\" 200 3781"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:31:27-05:00",
            "message": "252.0.0.0 - - [2020-04-30T14:31:27-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:31:29-05:00",
            "message": "247.37.0.0 - - [2020-04-30T14:31:29-05:00] \"GET /images/hm_brdl.gif HTTP/1.0\" 304 0"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:31:29-05:00",
            "message": "247.37.0.0 - - [2020-04-30T14:31:29-05:00] \"GET /images/hm_arw.gif HTTP/1.0\" 304 0"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:31:32-05:00",
            "message": "247.37.0.0 - - [2020-04-30T14:31:32-05:00] \"GET /images/nav_bg_top.gif HTTP/1.0\" 200 929"
        },
        {
            "index": {}
        },
        {
            "@timestamp": "2020-04-30T14:31:43-05:00",
            "message": "247.37.0.0 - - [2020-04-30T14:31:43-05:00] \"GET /french/images/nav_venue_off.gif HTTP/1.0\" 304 0"
        }
    ],
)
print(resp)
response = client.bulk(
  index: 'my-index-000001',
  refresh: true,
  body: [
    {
      index: {}
    },
    {
      "@timestamp": '2020-06-21T15:00:01-05:00',
      message: '211.11.9.0 - - [2020-06-21T15:00:01-05:00] "GET /english/index.html HTTP/1.0" 304 0'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-06-21T15:00:01-05:00',
      message: '211.11.9.0 - - [2020-06-21T15:00:01-05:00] "GET /english/index.html HTTP/1.0" 304 0'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:30:17-05:00',
      message: '40.135.0.0 - - [2020-04-30T14:30:17-05:00] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:30:53-05:00',
      message: '232.0.0.0 - - [2020-04-30T14:30:53-05:00] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:31:12-05:00',
      message: '26.1.0.0 - - [2020-04-30T14:31:12-05:00] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:31:19-05:00',
      message: '247.37.0.0 - - [2020-04-30T14:31:19-05:00] "GET /french/splash_inet.html HTTP/1.0" 200 3781'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:31:27-05:00',
      message: '252.0.0.0 - - [2020-04-30T14:31:27-05:00] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:31:29-05:00',
      message: '247.37.0.0 - - [2020-04-30T14:31:29-05:00] "GET /images/hm_brdl.gif HTTP/1.0" 304 0'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:31:29-05:00',
      message: '247.37.0.0 - - [2020-04-30T14:31:29-05:00] "GET /images/hm_arw.gif HTTP/1.0" 304 0'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:31:32-05:00',
      message: '247.37.0.0 - - [2020-04-30T14:31:32-05:00] "GET /images/nav_bg_top.gif HTTP/1.0" 200 929'
    },
    {
      index: {}
    },
    {
      "@timestamp": '2020-04-30T14:31:43-05:00',
      message: '247.37.0.0 - - [2020-04-30T14:31:43-05:00] "GET /french/images/nav_venue_off.gif HTTP/1.0" 304 0'
    }
  ]
)
puts response
const response = await client.bulk({
  index: "my-index-000001",
  refresh: "true",
  operations: [
    {
      index: {},
    },
    {
      "@timestamp": "2020-06-21T15:00:01-05:00",
      message:
        '211.11.9.0 - - [2020-06-21T15:00:01-05:00] "GET /english/index.html HTTP/1.0" 304 0',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-06-21T15:00:01-05:00",
      message:
        '211.11.9.0 - - [2020-06-21T15:00:01-05:00] "GET /english/index.html HTTP/1.0" 304 0',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:30:17-05:00",
      message:
        '40.135.0.0 - - [2020-04-30T14:30:17-05:00] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:30:53-05:00",
      message:
        '232.0.0.0 - - [2020-04-30T14:30:53-05:00] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:31:12-05:00",
      message:
        '26.1.0.0 - - [2020-04-30T14:31:12-05:00] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:31:19-05:00",
      message:
        '247.37.0.0 - - [2020-04-30T14:31:19-05:00] "GET /french/splash_inet.html HTTP/1.0" 200 3781',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:31:27-05:00",
      message:
        '252.0.0.0 - - [2020-04-30T14:31:27-05:00] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:31:29-05:00",
      message:
        '247.37.0.0 - - [2020-04-30T14:31:29-05:00] "GET /images/hm_brdl.gif HTTP/1.0" 304 0',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:31:29-05:00",
      message:
        '247.37.0.0 - - [2020-04-30T14:31:29-05:00] "GET /images/hm_arw.gif HTTP/1.0" 304 0',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:31:32-05:00",
      message:
        '247.37.0.0 - - [2020-04-30T14:31:32-05:00] "GET /images/nav_bg_top.gif HTTP/1.0" 200 929',
    },
    {
      index: {},
    },
    {
      "@timestamp": "2020-04-30T14:31:43-05:00",
      message:
        '247.37.0.0 - - [2020-04-30T14:31:43-05:00] "GET /french/images/nav_venue_off.gif HTTP/1.0" 304 0',
    },
  ],
});
console.log(response);
POST /my-index-000001/_bulk?refresh
{ "index": {}}
{ "@timestamp": "2020-06-21T15:00:01-05:00", "message" : "211.11.9.0 - - [2020-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0"}
{ "index": {}}
{ "@timestamp": "2020-06-21T15:00:01-05:00", "message" : "211.11.9.0 - - [2020-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:30:17-05:00", "message" : "40.135.0.0 - - [2020-04-30T14:30:17-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:30:53-05:00", "message" : "232.0.0.0 - - [2020-04-30T14:30:53-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:31:12-05:00", "message" : "26.1.0.0 - - [2020-04-30T14:31:12-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:31:19-05:00", "message" : "247.37.0.0 - - [2020-04-30T14:31:19-05:00] \"GET /french/splash_inet.html HTTP/1.0\" 200 3781"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:31:27-05:00", "message" : "252.0.0.0 - - [2020-04-30T14:31:27-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:31:29-05:00", "message" : "247.37.0.0 - - [2020-04-30T14:31:29-05:00] \"GET /images/hm_brdl.gif HTTP/1.0\" 304 0"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:31:29-05:00", "message" : "247.37.0.0 - - [2020-04-30T14:31:29-05:00] \"GET /images/hm_arw.gif HTTP/1.0\" 304 0"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:31:32-05:00", "message" : "247.37.0.0 - - [2020-04-30T14:31:32-05:00] \"GET /images/nav_bg_top.gif HTTP/1.0\" 200 929"}
{ "index": {}}
{ "@timestamp": "2020-04-30T14:31:43-05:00", "message" : "247.37.0.0 - - [2020-04-30T14:31:43-05:00] \"GET /french/images/nav_venue_off.gif HTTP/1.0\" 304 0"}

Поиск рассчитанного дня недели

Следующий запрос использует API поиска для получения поля day_of_week, которое исходный запрос определил как поле в реальном времени в схеме. Значение этого поля вычисляется динамически во время запроса без повторной индексации документов или индексации поля day_of_week. Эта гибкость позволяет изменять схему, не изменяя значения полей.

resp = client.search(
    index="my-index-000001",
    fields=[
        "@timestamp",
        "day_of_week"
    ],
    source=False,
)
print(resp)
response = client.search(
  index: 'my-index-000001',
  body: {
    fields: [
      '@timestamp',
      'day_of_week'
    ],
    _source: false
  }
)
puts response
const response = await client.search({
  index: "my-index-000001",
  fields: ["@timestamp", "day_of_week"],
  _source: false,
});
console.log(response);
GET my-index-000001/_search
{
  "fields": [
    "@timestamp",
    "day_of_week"
  ],
  "_source": false
}

Предыдущий запрос возвращает поле day_of_week для всех соответствующих документов. Мы можем определить другое поле в реальном времени, названное client_ip, которое также работает с полем message и дополнительно уточнит запрос:

resp = client.indices.put_mapping(
    index="my-index-000001",
    runtime={
        "client_ip": {
            "type": "ip",
            "script": {
                "source": "String m = doc[\"message\"].value; int end = m.indexOf(\" \"); emit(m.substring(0, end));"
            }
        }
    },
)
print(resp)
response = client.indices.put_mapping(
  index: 'my-index-000001',
  body: {
    runtime: {
      client_ip: {
        type: 'ip',
        script: {
          source: 'String m = doc["message"].value; int end = m.indexOf(" "); emit(m.substring(0, end));'
        }
      }
    }
  }
)
puts response
const response = await client.indices.putMapping({
  index: "my-index-000001",
  runtime: {
    client_ip: {
      type: "ip",
      script: {
        source:
          'String m = doc["message"].value; int end = m.indexOf(" "); emit(m.substring(0, end));',
      },
    },
  },
});
console.log(response);
PUT /my-index-000001/_mapping
{
  "runtime": {
    "client_ip": {
      "type": "ip",
      "script" : {
      "source" : "String m = doc[\"message\"].value; int end = m.indexOf(\" \"); emit(m.substring(0, end));"
      }
    }
  }
}

Выполните другой запрос, но найдите определенный IP-адрес, используя поле в реальном времени client_ip:

resp = client.search(
    index="my-index-000001",
    size=1,
    query={
        "match": {
            "client_ip": "211.11.9.0"
        }
    },
    fields=[
        "*"
    ],
)
print(resp)
const response = await client.search({
  index: "my-index-000001",
  size: 1,
  query: {
    match: {
      client_ip: "211.11.9.0",
    },
  },
  fields: ["*"],
});
console.log(response);
GET my-index-000001/_search
{
  "size": 1,
  "query": {
    "match": {
      "client_ip": "211.11.9.0"
    }
  },
  "fields" : ["*"]
}

На этот раз в ответе содержится только два совпадения. Значение для day_of_week (Sunday) было вычислено во время запроса с использованием скрипта в реальном времени, определенного в схеме, и результат включает только документы, соответствующие IP-адресу 211.11.9.0.

{
  ...
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_id" : "oWs5KXYB-XyJbifr9mrz",
        "_score" : 1.0,
        "_source" : {
          "@timestamp" : "2020-06-21T15:00:01-05:00",
          "message" : "211.11.9.0 - - [2020-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0"
        },
        "fields" : {
          "@timestamp" : [
            "2020-06-21T20:00:01.000Z"
          ],
          "client_ip" : [
            "211.11.9.0"
          ],
          "message" : [
            "211.11.9.0 - - [2020-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0"
          ],
          "day_of_week" : [
            "Sunday"
          ]
        }
      }
    ]
  }
}

Получение полей из связанных индексов

Параметр fields в API _search также может быть использован для получения полей из связанных индексов через поля в реальном времени с типом lookup.

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

resp = client.index(
    index="ip_location",
    refresh=True,
    document={
        "ip": "192.168.1.1",
        "country": "Canada",
        "city": "Montreal"
    },
)
print(resp)

resp1 = client.index(
    index="logs",
    id="1",
    refresh=True,
    document={
        "host": "192.168.1.1",
        "message": "the first message"
    },
)
print(resp1)

resp2 = client.index(
    index="logs",
    id="2",
    refresh=True,
    document={
        "host": "192.168.1.2",
        "message": "the second message"
    },
)
print(resp2)

resp3 = client.search(
    index="logs",
    runtime_mappings={
        "location": {
            "type": "lookup",
            "target_index": "ip_location",
            "input_field": "host",
            "target_field": "ip",
            "fetch_fields": [
                "country",
                "city"
            ]
        }
    },
    fields=[
        "host",
        "message",
        "location"
    ],
    source=False,
)
print(resp3)
response = client.index(
  index: 'ip_location',
  refresh: true,
  body: {
    ip: '192.168.1.1',
    country: 'Canada',
    city: 'Montreal'
  }
)
puts response

response = client.index(
  index: 'logs',
  id: 1,
  refresh: true,
  body: {
    host: '192.168.1.1',
    message: 'the first message'
  }
)
puts response

response = client.index(
  index: 'logs',
  id: 2,
  refresh: true,
  body: {
    host: '192.168.1.2',
    message: 'the second message'
  }
)
puts response

response = client.search(
  index: 'logs',
  body: {
    runtime_mappings: {
      location: {
        type: 'lookup',
        target_index: 'ip_location',
        input_field: 'host',
        target_field: 'ip',
        fetch_fields: [
          'country',
          'city'
        ]
      }
    },
    fields: [
      'host',
      'message',
      'location'
    ],
    _source: false
  }
)
puts response
const response = await client.index({
  index: "ip_location",
  refresh: "true",
  document: {
    ip: "192.168.1.1",
    country: "Canada",
    city: "Montreal",
  },
});
console.log(response);

const response1 = await client.index({
  index: "logs",
  id: 1,
  refresh: "true",
  document: {
    host: "192.168.1.1",
    message: "the first message",
  },
});
console.log(response1);

const response2 = await client.index({
  index: "logs",
  id: 2,
  refresh: "true",
  document: {
    host: "192.168.1.2",
    message: "the second message",
  },
});
console.log(response2);

const response3 = await client.search({
  index: "logs",
  runtime_mappings: {
    location: {
      type: "lookup",
      target_index: "ip_location",
      input_field: "host",
      target_field: "ip",
      fetch_fields: ["country", "city"],
    },
  },
  fields: ["host", "message", "location"],
  _source: false,
});
console.log(response3);
POST ip_location/_doc?refresh
{
  "ip": "192.168.1.1",
  "country": "Canada",
  "city": "Montreal"
}

PUT logs/_doc/1?refresh
{
  "host": "192.168.1.1",
  "message": "the first message"
}

PUT logs/_doc/2?refresh
{
  "host": "192.168.1.2",
  "message": "the second message"
}

POST logs/_search
{
  "runtime_mappings": {
    "location": {
        "type": "lookup", 
        "target_index": "ip_location", 
        "input_field": "host", 
        "target_field": "ip", 
        "fetch_fields": ["country", "city"] 
    }
  },
  "fields": [
    "host",
    "message",
    "location"
  ],
  "_source": false
}

Определите поле в реальном времени в основном запросе поиска с типом lookup, которое получает поля из целевого индекса с помощью запросов term.

Целевой индекс, в котором выполняется запрос поиска

Поле в основном индексе, значения которого используются как входные значения запроса поиска с использованием слова

Поле в индексе поиска, против которого выполняется запрос поиска с использованием слова

Список полей для получения из индекса поиска. См. параметр fields запроса поиска.

Вышеупомянутый запрос возвращает страну и город из индекса ip_location для каждого IP-адреса возвращаемых результатов поиска.

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "logs",
        "_id": "1",
        "_score": 1.0,
        "fields": {
          "host": [ "192.168.1.1" ],
          "location": [
            {
              "city": [ "Montreal" ],
              "country": [ "Canada" ]
            }
          ],
          "message": [ "the first message" ]
        }
      },
      {
        "_index": "logs",
        "_id": "2",
        "_score": 1.0,
        "fields": {
          "host": [ "192.168.1.2" ],
          "message": [ "the second message" ]
        }
      }
    ]
  }
}

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

© 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/runtime-retrieving-fields.html

Spec-Zone.ru

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