ElasticSearch Nested NumericRangeQuery usando o valor mínimo da lista para comparação

Sep 25 2020

Tenho os seguintes dados:

[{
    "id": "1",
    "listItems": [
        {
            "key": "li1",
            "value": 100
        },
        {
            "key": "li2",
            "value": 5000
        }
    ]
},
{
    "id": "2",
    "listItems": [
        {
            "key": "li3",
            "value": 200
        },
        {
            "key": "li2",
            "value": 2000
        }
    ]
}]

Estou tentando fazer um filtro NumericRangeQuery para que o valor MIN em cada listItems do documento corresponda entre um intervalo. Por exemplo, meu intervalo é de 150 a 15.000.

A única maneira que conheço de escrever isso é usando uma consulta de script, mas ela não parece funcionar, pois o código ainda parece pegar qualquer valor em listItems para tentar corresponder ao intervalo em vez de pegar o MIN como eu disse para. Esta é a minha consulta:

{
"track_total_hits": true,
"from": 0,
"min_score": 0.0,
"query": {
    "bool": {
        "must": [
            {
                "nested": {
                    "path": "listItems",
                    "query": {
                        "script": {
                            "script": "double minVal = 0; minVal = doc['listItems.value'][0]; for (wp in doc['listItems.value']) {if (wp < minVal) { minVal = wp;}} return minVal >= 150 && minVal <= 15000"
                        }
                    }
                }
            }
        ]
    }
}}

Alguém está vendo algo que eu não vejo?

Respostas

2 ESCoder Sep 26 2020 at 03:23

A consulta de pesquisa realiza a seguinte agregação:

  1. Agregação de termos no idcampo
  2. Agregação mínima emlistItems.value
  3. Agregação Bucket Selector que é uma agregação de pipeline pai que executa um script que determina se o bucket atual será retido na agregação multi-bucket pai.

Adicionar um exemplo funcional com mapeamento de índice, dados de índice, consulta de pesquisa e resultado de pesquisa

Mapeamento de índice:

{
  "mappings": {
    "properties": {
      "listItems": {
        "type": "nested" 
      },
      "id":{
        "type":"text",
        "fielddata":"true"
      }
    }
  }
}

Dados do índice:

{
    "id" : "1",
    "listItems" : 
        [
            {
                "key" : "li1",
                "value" : 100
            },
            {
                "key" : "li2",
                "value" : 5000
            }
        ]
}
{
    "id" : "2",
    "listItems" : 
        [
            {
                "key" : "li3",
                "value" : 200
            },
            {
                "key" : "li2",
                "value" : 2000
            }
        ]
}

Consulta de pesquisa:

{
    "size": 0,
    "aggs": {
        "id_terms": {
            "terms": {
                "field": "id"
            },
            "aggs": {
                "nested_entries": {
                    "nested": {
                        "path": "listItems"
                    },
                    "aggs": {
                        "min_position": {
                            "min": {
                                "field": "listItems.value"
                            }
                        }
                    }
                },
                "value_range": {
                    "bucket_selector": {
                        "buckets_path": {
                            "totalValues": "nested_entries>min_position"
                        },
                        "script": "params.totalValues >= 150 && params.totalValues < 15000"
                    }
                }
            }
        }
    }
}

Resultado da pesquisa:

"aggregations": {
    "id_terms": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "2",
          "doc_count": 1,
          "nested_entries": {
            "doc_count": 2,
            "min_position": {
              "value": 200.0
            }
          }
        }
      ]
    }
  }