Включить/исключить документы из группы terms aggs

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

Документы
{
    "id": 1,
    "status": 1,
    "data": {"reference": 1, "upc": 1 }
}

{
    "id": 2,
    "status": 2,
    "data": {"reference": 1, "upc": 2 }
}

{
    "id": 3,
    "status": 1,
    "data": {"reference": 1, "upc": 3 }
}

Нужно найти эти документы только если в группе объеденнёных документов, есть документ с "status": 2, если в группе нет документа с таким статусом, то вся группа должна отсутстовать в результатах.
Сами документы группируются по полю data.reference
Сейчас поиск работает по такому запросу и в нём не учитывается статус.

Запрос
{
  "size": 0,
  "aggs": {
    "products": {
      "composite": {
        "size": 200,
        
        "sources": [
          {
            "by_merge_field": {
              "terms": {
                "script": {
                  "source": """
                    if(!doc['data.reference.keyword'].empty) {
                        return doc['data.reference.keyword'].value
                    }
                    
                    if(!doc['data.upc.keyword'].empty) {
                        return doc['data.upc.keyword'].value
                    }
          
                    return null
                  """,
                  "lang": "painless"
                }
              }
            }
          }
        ]
      },
      "aggs": {
        "docs": {
          "top_hits": {
            "_source": {
              "includes": ""
            }
          }
        }
      }
    }
  }
}

Если я вас правильно понял, то можно с агрегацией filter и bucket_selector:

DELETE test

POST test/_bulk
{"index":{}}
{"id":1,"status":1,"data":{"reference":1,"upc":1}}
{"index":{}}
{"id":2,"status":2,"data":{"reference":1,"upc":2}}
{"index":{}}
{"id":3,"status":1,"data":{"reference":1,"upc":3}}
{"index":{}}
{"id":4,"status":1,"data":{"reference":2,"upc":1}}
{"index":{}}
{"id":5,"status":1,"data":{"reference":2,"upc":4}}
{"index":{}}
{"id":6,"status":2,"data":{"reference":3,"upc":1}}
{"index":{}}
{"id":7,"status":2,"data":{"reference":3,"upc":4}}

GET test/_search
{
  "size": 0,
  "aggs": {
    "by_reference": {
      "terms": {
        "field": "data.reference",
        "size": 10
      },
      "aggs": {
        "with_status_2": {
          "filter": {
            "term": {
              "status": {
                "value": "2"
              }
            }
          }
        },
        "my_selector": {
          "bucket_selector": {
            "buckets_path": {
              "status_found": "with_status_2._count"
            },
            "script": "params.status_found > 0"
          }
        }
      }
    }
  }
}

Спасибо, работает!
Можно ли bucket_selector подружить с composite ?
Агрегацию composite использую только для пагинации

Нет, но можно добавить "order": { "_key": "asc" } и завернуть все в filter agg с запросом range, чтобы только получить записи, в которых значения поля data.reference больше последнего значения, которое мы видели. То есть, если последнее значение data.reference было 33, то запрос будет такой:

GET test/_search
{
  "size": 0,
  "aggs": {
    "paging": {
      "filter": {
        "range": {
          "data.reference": {
            "gt": 33
          }
        }
      },
      "aggs": {
        "by_reference": {
          "terms": {
            "field": "data.reference",
            "size": 10,
            "order": {
              "_key": "asc"
            }
          },
          "aggs": {
            "with_status_2": {
              "filter": {
                "term": {
                  "status": {
                    "value": "2"
                  }
                }
              }
            },
            "my_selector": {
              "bucket_selector": {
                "buckets_path": {
                  "status_found": "with_status_2._count"
                },
                "script": "params.status_found > 0"
              }
            }
          }
        }
      }
    }
  }
}

Спасибо! Буду пробовать

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.