Безболезненный скрипт для получения разницы во времени между двумя записями журнала, разделенными уникальным идентификатором

Я пытаюсь получить разницу во времени между двумя записями журнала, такими как RequestExecuted и RequestReceived, с именем MessageIdentifier. Эти значения связаны уникальным идентификатором TransactionId. Ниже мой код для выполнения логики.

int timetaken=0;      
int start=0;      
String TransactionId;      
int end=0;   

for(int i = 0; i < 10; ++i){        
    if (doc['dissect.MessageIdentifier'].value[i]=='RequestReceived') {          
        start=params._source.dissect.timestamp[i];          
        TransactionId=params._source.dissect.TransactionId[i];
     }        
    if( doc['dissect.MessageIdentifier'].value[i] =='RequestExecuted' 
        && params._source.dissect.TransactionId == TransactionId) {          
            end=params._source.dissect.timestamp[i];          
            timetaken = end - start; 
            return timetaken;
    }
}

Когда я компилирую свой безболезненный скрипт, он выдает ошибку:

lang": "painless",
    "caused_by": {
     "type": "illegal_argument_exception",
     "reason": "Attempting to address a non-array-like type [java.lang.String] as an array."

Вот фрагмент индекса:

введите здесь описание изображения

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


person Muntazir Abbas    schedule 04.05.2020    source источник
comment
Что вы повторяете с for (int i = 0; i < 10; ++i)? У вас есть доступ только к контексту текущего документа, а не ко всему. Кроме того, вы используете script_fields или scripted_metric aggs?   -  person Joe Sorocin    schedule 04.05.2020
comment
Это то, что вам нужно сделать во время загрузки (например, с помощью Logstash). См. эту тему: stackoverflow.com/questions/37353365/   -  person Val    schedule 05.05.2020
comment
@jzzfs На самом деле я перебираю размер документа. это просто пример. Я использую скриптовую матричную агрессию. Logstash на самом деле не вариант здесь. Вот почему вы пытаетесь создать файл со сценарием, когда данные уже находятся в elasticsearch.   -  person Muntazir Abbas    schedule 05.05.2020
comment
так что ваше поле dissect представляет собой массив элементов?   -  person Joe Sorocin    schedule 05.05.2020
comment
@jzzfs да, это так.   -  person Muntazir Abbas    schedule 05.05.2020


Ответы (1)


Предполагая, что ваше поле dissect представляет собой массив вложенных объектов, вы можете сделать следующее:

Создать индекс

PUT dissect
{
  "mappings": {
    "properties": {
       "dissect" : {
         "type": "nested", 
          "properties" : {
            "MessageIdentifier" : {
              "type" : "text",
              "fielddata": true,
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "TransationId" : {
              "type" : "text",
              "fielddata": true,
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "timestamp" : {
              "type" : "date"
            }
          }
        }
    }
  }
}

Синхронизировать образец

POST dissect/_doc
{
  "dissect": [
    {
      "MessageIdentifier": "abc",
      "timestamp": 200,
      "TransationId": "xyz"
    },
    {
      "MessageIdentifier": "RequestReceived",
      "timestamp": 300,
      "TransationId": "xyz"
    },
    {
      "MessageIdentifier": "RequestExecuted",
      "timestamp": 400,
      "TransationId": "xyz"
    }
  ]
}

Запустите поле сценария

GET dissect/_search
{
  "script_fields": {
    "timetaken": {
      "script": {
        "source": """
        int timetaken = 0;      
        int start = 0;      
        String TransactionId;      
        int end = 0;   

        for (def dissect_item : params._source['dissect']) {
          if (dissect_item['MessageIdentifier'] == 'RequestReceived') {          
                start = dissect_item['timestamp'];          
                TransactionId = dissect_item['TransactionId'];
            }

            if( dissect_item['MessageIdentifier'] =='RequestExecuted' 
                && dissect_item['TransactionId'] == TransactionId) {          
                    end = dissect_item['timestamp'];          
                    timetaken = end - start; 
                    return timetaken;
            }
        }
        """
      }
    }
  }
}

уступающий

[
  {
    "_index":"dissect",
    "_type":"_doc",
    "_id":"_v7u43EBW-D5QnrWmjtM",
    "_score":1.0,
    "fields":{
      "timetaken":[
        100              <-----
      ]
    }
  }
]

Ключевой вывод: вы не хотите перебирать жестко закодированную длину 10, а вместо этого for (def dissect_item : params._source['dissect'])

person Joe Sorocin    schedule 05.05.2020
comment
человек большое спасибо. Это именно то, что я хотел. И ваш ответ объяснил всю концепцию. Я был новичком в безболезненном, но теперь лучше понимаю. Большое спасибо. - person Muntazir Abbas; 05.05.2020