Использовать результат запроса как параметр для другого запроса в 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, платное предложение.