Как фильтровать вложенные агрегаты в ElasticSearch? - PullRequest
0 голосов
/ 10 июля 2020

Например, предположим, что у нас есть индекс продукта со следующим отображением:

 {
  "product": {
    "mappings": {
      "producttype": {
        "properties": {
          "id": {
            "type": "keyword"
          },
          "productAttributes": {
            "type": "nested",
            "properties": {
              "name": {
                "type": "keyword"
              },
              "value": {
                "type": "keyword"
              }
            }
          },
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "text",
                "analyzer": "keyword"
              }
            },
            "analyzer": "standard"
          }
        }
      }
    }
  }
}

Я пытаюсь найти, сколько продуктов с определенными атрибутами c продукта, используя следующий запрос (я используя нечеткий запрос, чтобы разрешить некоторое расстояние редактирования):

  {
  "size": 0,
  "query": {
    "nested": {
      "query": {
        "fuzzy": {
          "productAttributes.name": {
            "value": "SSD"
          }
        }
      },
      "path": "productAttributes"
    }
  },
  "aggs": {
    "product_attribute_nested_agg": {
      "nested": {
        "path": "productAttributes"
      },
      "aggs": {
        "terms_nested_agg": {
          "terms": {
            "field": "productAttributes.name"
          }
        }
      }
    }
  }
}

Но он возвращает все атрибуты продукта для каждого согласованного документа, и вот ответ, который я получаю.

  "aggregations" : {
    "product_attribute_nested_agg" : {
      "doc_count" : 6,
      "terms_nested_agg" : {
        "doc_count_error_upper_bound" : 0,
        "sum_other_doc_count" : 0,
        "buckets" : [
          {
            "key" : "SSD",
            "doc_count" : 3
          },
          {
            "key" : "USB 2.0",
            "doc_count" : 3
          }
        ]
      }
    }
  }

Не могли бы вы подскажите, как фильтровать сегменты, чтобы возвращать только совпадающие атрибуты?

Изменить: Вот несколько примеров документов:

  "hits" : {
    "total" : 12,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "product",
        "_type" : "producttype",
        "_id" : "677d1164-c401-4d36-8a08-6aa14f7f32bb",
        "_score" : 1.0,
        "_source" : {
          "title" : "Dell laptop",
          "productAttributes" : [
            {
              "name" : "USB 2.0",
              "value" : "4"
            },
            {
              "name" : "SSD",
              "value" : "250 GB"
            }
          ]
        }
      },
      {
        "_index" : "product",
        "_type" : "producttype",
        "_id" : "2954935a-7f60-437a-8a54-00da2d71da46",
        "_score" : 1.0,
        "_source" : {
          "productAttributes" : [
            {
              "name" : "USB 2.0",
              "value" : "3"
            },
            {
              "name" : "SSD",
              "value" : "500 GB"
            }
          ],
          "title" : "HP laptop"
        }
      },
    ]
  }

1 Ответ

1 голос
/ 10 июля 2020

Чтобы отфильтровать только определенные c, вы можете использовать filter запросы.

Запрос:

{
  "size": 0,
  "aggs": {
    "product_attribute_nested_agg": {
      "nested": {
        "path": "productAttributes"
      },
      "aggs": {
        "inner": {
          "filter": {
            "terms": {
              "productAttributes.name": [
                "SSD"
              ]
            }
          },
          "aggs": {
            "terms_nested_agg": {
              "terms": {
                "field": "productAttributes.name"
              }
            }
          }
        }
      }
    }
  }
}

Вот что он делает:

"filter": {
  "terms": {
    "productAttributes.name": [
      "SSD"
    ]
  }
}

Вам нужно выполнить фильтрующую часть агрегации.

Вывод:

"aggregations": {
  "product_attribute_nested_agg": {
    "doc_count": 4,
    "inner": {
      "doc_count": 2,
      "terms_nested_agg": {
        "doc_count_error_upper_bound": 0,
        "sum_other_doc_count": 0,
        "buckets": [
          {
            "key": "SSD",
            "doc_count": 2
          }
        ]
      }
    }
  }
}

Фильтрация с использованием нечеткости:

GET /product/_search
{
  "size": 0,
  "aggs": {
    "product_attribute_nested_agg": {
      "nested": {
        "path": "productAttributes"
      },
      "aggs": {
        "inner": {
          "filter": {
           "fuzzy": {
                "productAttributes.name": {
                  "value": "SSt",//here will match SSD
                  "fuzziness": 3//you can remove it to be as Auto
                }
              }
          },
          "aggs": {
            "terms_nested_agg": {
              "terms": {
                "field": "productAttributes.name"
              }
            }
          }
        }
      }
    }
  }
}
...