Использовать результат запроса как параметр для другого запроса в Elasticsearch DSL

Я использую Elasticsearch DSL, я пытаюсь использовать результат запроса в качестве параметра для другого запроса, как показано ниже:

      {
  "query": {
    "bool": {
      "must_not": {
        "terms": {
          "request_id": {
            "query": {
              "match": {
                "processing.message": "OUT Followup Synthesis"
              }
            },
            "fields": [
              "request_id"
            ],
            "_source": false
          }
        }
      }
    }
  }
}

Как вы можете видеть выше, я пытаюсь найти источники, request_id не один из request_idsс processing.message равно OUT Followup Synthesis.

Я получаю сообщение об ошибке с этим запросом:

      Error loading data [x_content_parse_exception] [1:1660] [terms_lookup] unknown field [query]

Как я могу достичь своей цели с помощью Elasticsearch DSL?

1 ответ

Исходный вопрос извлечен из комментариев

Я пытаюсь получить данные с processing.message равно «IN Followup Sythesis», а их request_id не отображается в данных с processing.message равно «OUT Followup Sythesis». На языке SQL:

      SELECT d FROM   data d
WHERE  d.processing.message = 'IN Followup Sythesis'
       AND d.request_id NOT IN (SELECT request_id FROM data WHERE processing.message = 'OUT Followup Sythesis'); 

Ответ: вообще говоря, в Elasticsearch не поддерживаются ни соединения на стороне приложения, ни подзапросы .

Таким образом, вам нужно будет выполнить свой первый запрос, взять полученные идентификаторы и поместить их во второй запрос - в идеале <tcode id="373064"></tcode>запрос .


Конечно, это ограничение можно преодолеть, «взломав» скрипт агрегирования показателей .

Взяв эти 3 документа в качестве примера:

      POST reqs/_doc
{"request_id":"abc","processing":{"message":"OUT Followup Synthesis"}}

POST reqs/_doc
{"request_id":"abc","processing":{"message":"IN Followup Sythesis"}}

POST reqs/_doc
{"request_id":"xyz","processing":{"message":"IN Followup Sythesis"}}

ты мог бежать

      POST reqs/_search
{
  "size": 0,
  "query": {
    "match": {
      "processing.message": "IN Followup Sythesis"
    }
  },
  "aggs": {
    "subquery_mock": {
      "scripted_metric": {
        "params": {
          "disallowed_msg": "OUT Followup Synthesis"
        }, 
        "init_script": "state.by_request_ids = [:]; state.disallowed_request_ids = [];",
        "map_script": """
          def req_id = params._source.request_id;
          def msg = params._source.processing.message;
          
          if (msg.contains(params.disallowed_msg)) {
            state.disallowed_request_ids.add(req_id);
            // won't need this particular doc so continue looping
            return;
          }
          
          if (state.by_request_ids.containsKey(req_id)) {
            // there may be multiple docs under the same ID
            // so concatenate them
            state.by_request_ids[req_id].add(params._source);
          } else {
            // initialize an appendable arraylist
            state.by_request_ids[req_id] = [params._source];
          }
        """,
        "combine_script": """
          state.by_request_ids.entrySet()
            .removeIf(entry -> state.disallowed_request_ids.contains(entry.getKey()));
          return state.by_request_ids
        """,
        "reduce_script": "return states"
      }
    }
  }
}

который вернет только правильный запрос:

      "aggregations" : {
  "subquery_mock" : {
    "value" : [
      {
        "xyz" : [
          {
            "processing" : { "message" : "IN Followup Sythesis" },
            "request_id" : "xyz"
          }
        ]
      }
    ]
  }
}

⚠️ Это почти гарантированно будет медленным и противоречит предлагаемым рекомендациям, запрещающим доступ к <tcode id="373068"></tcode>поле . Но это также показывает, что подзапросы можно «эмулировать».

💡 Я бы порекомендовал протестировать этот скрипт на меньшем наборе документов, прежде чем разрешить ему таргетинг на весь ваш индекс - возможно, ограничьте его датой <tcode id="373069"></tcode>запрос или аналогичный.


FYI Elasticsearch предоставляет SQL API, хотя он предлагается только через X-Pack, платное предложение.

Другие вопросы по тегам