Общей проблемой в интерфейсах поиска является то, что вы хотите вернуть выбор результатов, , но можете захотеть вернуть информацию обо всех документах. (например, я хочу видеть все красные рубашки, но хочу знать, что другие цвета доступны).Что отличается между постфильтром и глобальной агрегацией для фасетного поиска?
Это иногда называют «гранеными результатами», или «граненый навигация». example from the Elasticsearch reference совершенно ясно объясняет, почему/как, так Я использовал это как основу для этого вопроса.
Резюме/вопрос: Похоже, я могу использовать как постфильтр, так и глобальную агрегацию для этого. Оба они кажутся , предоставляют ту же функциональность по-другому. Могут быть преимущества или недостатки для них, которые я не вижу? ? Если да, то какой я должен использовать?
В приведенном ниже примере приведен полный пример с некоторыми документами и запрос с использованием обоих типов методов на основе примера .
Вариант 1: постфильтр
см example from the Elasticsearch reference
Что мы можем сделать, это иметь больше результатов в нашем оригинальный запрос, поэтому мы можем объединить «на» этих результатов, и затем отфильтровать наши фактические результаты.
Пример совершенно ясно объяснить это:
Но, возможно, вы хотели бы также, чтобы сообщить пользователю, сколько рубашки Gucci доступна в других цветах. Если вы просто добавите агрегирование терминов в поле цвета, вы получите только красный цвет, потому что ваш запрос возвращает только красные рубашки Gucci.
Вместо этого вы хотите включить рубашки всех цветов во время агрегации, а затем применить фильтр цветов только к результатам поиска.
Посмотрите, как это будет выглядеть ниже в примере кода.
Проблема в том, что мы не можем использовать кеширование. Это в (пока не доступны для 5.1) elasticsearch guide предупреждено о:
рассмотрении эффективности используйте устройство post_filter только если вам нужно дифференцированно результаты поиска фильтров и агрегаты. Иногда люди будут использовать post_filter для регулярного поиска.
Не делайте этого! Характер post_filter означает, что он запускается после запроса, поэтому любое преимущество в производительности фильтрации (например, кеши) полностью теряется.
Post_filter следует использовать только в сочетании с агрегатами и только тогда, когда вам нужна дифференциальная фильтрация.
Существует, однако, другой вариант:
Вариант 2: глобальные скопления
Существует способ сделать агрегацию, который не зависит от поискового запроса. Итак, вместо того, чтобы получать много, агрегировать на этом, а затем фильтровать, мы просто получаем отфильтрованные результаты, но делаем агрегации по всем. Взгляните at the reference
Мы можем получить точные результаты. Я не читал никаких предупреждений о кешировании для этого, но, похоже, в конце нам нужно сделать примерно столько же работы. Так что, может быть, единственное исключение.
Это чуть-чуть более сложным из-за суб-агрегации мы должны (вы не можете иметь global
и filter
на же «уровень»).
Единственная жалоба, которую я прочитал о запросах, используя это, заключается в том, что вам, возможно, придется повторить, если вам нужно сделать это для нескольких предметов. В конце концов, мы можем генерировать большинство запросов, поэтому повторение самих себя не так уж и важно для моего usecase, , и я действительно не считаю это проблемой на уровне с «не может использовать кеш».
Вопрос
кажется обе функции накладываются друг на друга в меньшей мере, или, возможно, обеспечивая ту же самую функциональность. Это меня озадачивает. Помимо этого, я хотел бы знать, имеет ли тот или иной преимущество, которого я не видел, и если здесь есть какая-то лучшая практика?
Пример
Это в значительной степени от post-filter reference page, но я добавил global filter запрос.
картирования и документы
PUT /shirts
{
"mappings": {
"item": {
"properties": {
"brand": { "type": "keyword"},
"color": { "type": "keyword"},
"model": { "type": "keyword"}
}
}
}
}
PUT /shirts/item/1?refresh
{
"brand": "gucci",
"color": "red",
"model": "slim"
}
PUT /shirts/item/2?refresh
{
"brand": "gucci",
"color": "blue",
"model": "slim"
}
PUT /shirts/item/3?refresh
{
"brand": "gucci",
"color": "red",
"model": "normal"
}
PUT /shirts/item/4?refresh
{
"brand": "gucci",
"color": "blue",
"model": "wide"
}
PUT /shirts/item/5?refresh
{
"brand": "nike",
"color": "blue",
"model": "wide"
}
PUT /shirts/item/6?refresh
{
"brand": "nike",
"color": "red",
"model": "wide"
}
Теперь мы запрашивающие вся красный GUCCI рубашки (пункт 1 и 3), типы рубашек у нас есть (тонкие и нормальный) для этих 2 рубашки, и какие цвета Гуччей есть (красный и синий).
Во-первых, фильтр почты: получите все рубашки, соберите модели для красных рубашек gucci и цвета для рубашек gucci (все цвета), и пост-фильтр для красных рубашек gucci, чтобы показать только те, что были в результате: (это немного отличается от примера, как мы попытаться получить его как можно ближе к четкому применению Постфильтры как possilbe.)
GET /shirts/_search
{
"aggs": {
"colors_query": {
"filter": {
"term": {
"brand": "gucci"
}
},
"aggs": {
"colors": {
"terms": {
"field": "color"
}
}
}
},
"color_red": {
"filter": {
"bool": {
"filter": [
{
"term": {
"color": "red"
}
},
{
"term": {
"brand": "gucci"
}
}
]
}
},
"aggs": {
"models": {
"terms": {
"field": "model"
}
}
}
}
},
"post_filter": {
"bool": {
"filter": [
{
"term": {
"color": "red"
}
},
{
"term": {
"brand": "gucci"
}
}
]
}
}
}
мы могли бы также получить все красные GUCCI рубашки (наш оригинальный запрос), а затем сделайте глобальную агрегацию для модели (для всех красных рубашек gucci) и для цвета (для всех рубашек gucci).
GET /shirts/_search
{
"query": {
"bool": {
"filter": [
{ "term": { "color": "red" }},
{ "term": { "brand": "gucci" }}
]
}
},
"aggregations": {
"color_red": {
"global": {},
"aggs": {
"sub_color_red": {
"filter": {
"bool": {
"filter": [
{ "term": { "color": "red" }},
{ "term": { "brand": "gucci" }}
]
}
},
"aggs": {
"keywords": {
"terms": {
"field": "model"
}
}
}
}
}
},
"colors": {
"global": {},
"aggs": {
"sub_colors": {
"filter": {
"bool": {
"filter": [
{ "term": { "brand": "gucci" }}
]
}
},
"aggs": {
"keywords": {
"terms": {
"field": "color"
}
}
}
}
}
}
}
}
Оба будут возвращать одну и ту же информацию, вторая из них отличается только тем, что добавляется дополнительными уровнями, представленными суб-агрегатами. Второй запрос выглядит несколько сложнее, но я не думаю, что это очень проблематично.Запрос реального мира генерируется кодом, возможно, все более сложным, и он должен быть хорошим запросом, и если это будет сложно, пусть будет так.
Таким образом, они в конечном итоге выполняют те же функции, но пост-фильтр может иметь некоторые накладные расходы? Я мало знаю о коллекционерах люцен, не могли бы вы немного рассказать о том, что вы имеете в виду, или ударить меня ссылкой на то, что вы там указываете? – Nanne
Важным моментом в моем ответе является то, что это не имеет большого значения. Аргумент коллектора заключается в том, что в случае после фильтра трассировки стека имеют один уровень больше из-за использования MultiCollector, поскольку все выполняется за один проход, тогда как каждая глобальная агрегация выполняет другой проход по данным (но с запросом match_all) , – jpountz
Еще один способ попытаться решить эту проблему - отправить несколько запросов, по одному для каждого набора, который вы хотите проанализировать. Это устраняет гарантию того, что все запросы видят точно то же самое представление времени в индексе, но медленно изменяя данные, что, вероятно, приемлемо, и это также облегчает масштабирование, поскольку такие вещи, как кеш запросов, более вероятны быть задействованными. – jpountz