Сортировать сегменты агрегации эластичного поиска по текстовому полю - PullRequest
0 голосов
/ 25 октября 2019

Я пытаюсь отсортировать области результатов агрегации эластичного поиска. У меня большой набор документов:

"mappings": {
    "properties": {
        "price": {
            "type": "double"
        },
        "product_name": {
            "type": "text"
        },
        "product_id": {
            "type": "keyword"
        },
        "timestamp": {
            "type": "date"
        }
    }
}

В настоящее время я получаю последние продажи по каждому product_id с использованием агрегатов composite и top_hits:

{
    "query": {
        "bool": {
            "filter": [
                {
                    "range": {
                        "timestamp": {
                            "gte": "2019-10-25T00:00:00Z",
                            "lte": "2019-10-26T00:00:00Z"
                        }
                    }
                }
            ]
        }
    },
    "aggs": {
        "distinct_products": {
            "composite": {
                "sources": [
                    {
                        "distinct_ids": {
                            "terms": {
                                "field": "product_id"
                            }
                        }
                    }
                ],
                "size": 10000
            },
            "aggs": {
                "last_timestamp": {
                    "top_hits": {
                        "sort": {
                            "timestamp": {
                                "order": "desc"
                            }
                        },
                        "size": 1
                    }
                }
            }
        }
    }
}

Теперь я хочу отсортировать полученные сегменты по произвольному полю. Если я хочу отсортировать по price, я могу использовать решение в этом вопросе , добавив агрегацию max, которая извлекает поле product_price из каждого сегмента, и агрегацию bucket_sort вконец, который будет сортировать результаты max:

{
    "query": {
        "bool": {
            "filter": [
                {
                    "range": {
                        "timestamp": {
                            "gte": "2019-10-25T00:00:00Z",
                            "lte": "2019-10-26T00:00:00Z"
                        }
                    }
                }
            ]
        }
    },
    "aggs": {
        "distinct_products": {
            "composite": {
                "sources": [
                    {
                        "distinct_ids": {
                            "terms": {
                                "field": "product_id"
                            }
                        }
                    }
                ],
                "size": 10000
            },
            "aggs": {
                "last_timestamp": {
                    "top_hits": {
                        "sort": {
                            "timestamp": {
                                "order": "desc"
                            }
                        },
                        "size": 1,
                        "_source": {
                            "excludes": []
                        }
                    }
                },
                "latest_sell": {
                    "max": {
                        "field": "product_price"
                    }
                },
                "latest_sell_secondary": {
                    "max": {
                        "field": "timestamp"
                    }
                },
                "sort_sells": {
                    "bucket_sort": {
                        "sort": {
                            "latest_sell": {
                                "order": "desc"
                            },
                            "latest_sell_secondary": {
                                "order": "desc"
                            }
                        },
                        "from": 0,
                        "size": 10000
                    }
                }
            }
        }
    }
}

Если я хочу отсортировать по алфавиту по product_name вместо product_price, я не могу использовать агрегацию max, поскольку она работает только с числовымиfields.

Что можно сделать, чтобы отсортировать last_timestamp сегментов (в каждом из которых только один документ) по текстовому полю?

Используемая версия эластичного поиска7.2.0.

1 Ответ

0 голосов
/ 26 октября 2019

Из документов

Каждый сегмент может быть отсортирован по его _key, _count или его подгруппам

Вместо идентификатора продукта вы можете использовать product_name.keyword вУсловия агрегации и сортировки по ключу

"order": { "_key" : "asc" }
...