У меня есть товары с полем категорий. Используя агрегирование, я могу получить полные категории со всеми подкатегориями. Я хочу ограничить уровни в фасете.

Например У меня есть такие грани:

auto, tools & travel    (115)
auto, tools & travel > luggage tags (90)
auto, tools & travel > luggage tags > luggage spotters  (40)
auto, tools & travel > luggage tags > something else    (50)
auto, tools & travel > car organizers   (25)

Использование агрегации вроде

"aggs": {
    "cat_groups": {
      "terms": {
        "field": "categories.keyword",
        "size": 10,
       "include": "auto, tools & travel > .*"
      }
    }
}

Я получаю ведра вроде

"buckets": [
        {
          "auto, tools & travel > luggage tags",
          "doc_count": 90
        },
        {
          "key": "auto, tools & travel > luggage tags > luggage spotters",
          "doc_count": 40
        },
        {
          "key": "auto, tools & travel > luggage tags > something else",
          "doc_count": 50
        },
        {
          "key": "auto, tools & travel > car organizers",
          "doc_count": 25
        }
]

Но я хочу ограничить уровень. например Я хочу получить результаты только для auto, tools & travel > luggage tags. Как я могу ограничить уровни? Кстати, "exclude": ".* > .* > .*" у меня не работает.

Мне нужно получить ведра для разных уровней по запросу. Иногда первый уровень, а иногда второй или третий. Когда мне нужен первый уровень, я не хочу, чтобы вторые уровни отображались в корзинах; и так далее для других уровней.

Elasticsearch версии 6.4

2
Mainuddin 23 Окт 2018 в 06:36

2 ответа

Лучший ответ

Наконец, я смог понять методику ниже.

Я реализовал custom analyzer, используя Обозначение иерархии путей и я создали несколько полей под названием categories, чтобы вы могли использовать categories.facets для агрегирования / фасетов и выполнять обычный текстовый поиск с помощью categories.

Пользовательский анализатор будет применяться только для categories.facets

Обратите внимание на свойство "fielddata": "true" для моего поля categories.facet

Картографирование

PUT myindex
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "path_hierarchy",
          "delimiter": ">"
        }
      }
    }
  },
  "mappings": {
    "mydocs": {
      "properties": {
        "categories": {
          "type": "text",
          "fields": {
            "facet": { 
              "type":  "text",
              "analyzer": "my_analyzer",
              "fielddata": "true"
            }
          }
        }
      }
    }
  }
}

Образцы документов

POST myindex/mydocs/1
{
    "categories" : "auto, tools & travel > luggage tags > luggage spotters"
}

POST myindex/mydocs/2
{
    "categories" : "auto, tools & travel > luggage tags > luggage spotters"
}

POST myindex/mydocs/3
{
    "categories" : "auto, tools & travel > luggage tags > luggage spotters"
}

POST myindex/mydocs/4
{
    "categories" : "auto, tools & travel > luggage tags > something else"
}

Запрос

Вы можете попробовать следующий запрос, который ищете. Я снова реализовал фильтр Агрегация, потому что вам нужны только определенные слова вместе с Объединение терминов.

{
  "size": 0,
  "aggs":{
    "facets": {
      "filter": { 
          "bool": {
            "must": [
              { "match": { "categories": "luggage"} }
            ]
         }
      },
      "aggs": {
        "categories": {
          "terms": {
            "field": "categories.facet"
          }
        }
      }
    }
  }
}

Ответ

{
    "took": 43,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 11,
        "max_score": 0,
        "hits": []
    },
    "aggregations": {
        "facets": {
            "doc_count": 4,
            "categories": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                    {
                        "key": "auto, tools & travel ",
                        "doc_count": 4
                    },
                    {
                        "key": "auto, tools & travel > luggage tags ",
                        "doc_count": 4
                    },
                    {
                        "key": "auto, tools & travel > luggage tags > luggage spotters",
                        "doc_count": 3
                    },
                    {
                        "key": "auto, tools & travel > luggage tags > something else",
                        "doc_count": 1
                    }
                ]
            }
        }
    }
}

Обсуждение окончательного ответа в чате

POST myindex/_search
{
  "size": 0,
  "aggs":{
    "facets": {
      "filter": { 
          "bool": {
            "must": [
              { "match": { "categories": "luggage"} }
          ]
        }
      },
      "aggs": {
        "categories": {
          "terms": {
            "field": "categories.facet",
            "exclude": ".*>{1}.*>{1}.*"
          }
        }
      }
    }
  }
}

Обратите внимание, что я добавил exclude с regular expression таким образом, чтобы он не учитывал какие-либо аспекты, которые имеют более одного вхождения >

Дайте мне знать, если это поможет.

4
Opster ES Ninja - Kamal 4 Ноя 2018 в 19:30

Просто добавьте целочисленное поле с именем level, обозначающее уровень вашей категории в иерархии. Просто посчитайте количество вхождений вашего разделителя '>' и сохраните его как значение. Затем добавьте rangeQuery в свой boolQuery.

Добавьте это в свою схему:

"level": {
    "type": "integer",
    "store": "true",
    "index": "true"
}

В вашем коде у вас есть что-то вроде этого, которое подсчитывает количество разделителей, предлагающих уровень иерархии (без разделителей означает основную категорию):

public Builder(final String path) {
    this.path = path;
    this.level = StringUtils.countMatches(path, DELIMITER);
}

И тогда ваш поиск по запросу может иметь что-то вроде:

{
    "query": {
        "bool": {
            "filter": [
                {
                    "prefix": {
                        "category": {
                            "value": "auto, tools & travel",
                            "boost": 1
                        }
                    }
                },
                {
                    "range": {
                        "level": {
                            "from": 2,
                            "to": 4,
                            "include_lower": true,
                            "include_upper": true,
                            "boost": 1
                        }
                    }
                }
            ],
            "adjust_pure_negative": true,
            "boost": 1
        }
    }
}
0
Maica Ballangan 2 Апр 2019 в 15:58
52940790