Elasticsearch: как получить верхние уникальные значения поля, отсортированные по совпадению баллов? - PullRequest
0 голосов
/ 04 июня 2018

У меня есть коллекция адресов.Давайте упростим и скажем, что единственными полями являются postcode, city, street, streetnumber и name.Я хотел бы иметь возможность предложить список улиц, когда пользователь вводит почтовый индекс, город и некоторый запрос для улицы.

Например, если пользователь в форме HTML вводит:

postcode: 75010
city: Paris
street: rue des

Я хотел бы получить список улиц, таких как

'rue des petites écuries'
'rue des messageries'
...
'rue du faubourg poissonnière'
...

, которые я мог бы предложить пользователю.

Итак, я хотел бы получитьсписок уникальных значений поля "улица", отсортированный по тому, насколько они соответствуют моему запросу в поле "улица".Я хотел бы получить 10 наиболее подходящих улиц для этого запроса.

Запрос, возвращающий документы, будет выглядеть следующим образом:

{
    "query": {
        "bool": {
            "must": [
                {{"term": {"postcode": "75010"}},
                {{"term": {city": "Paris"}},
                {{"match": {"street": "rue des"}}
            ]    
        }
     }
}

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

Я попытался использовать структуру "агрегации" и добавил аггс:

{
    "query": {
        "bool": {
            "must": [
                {{"term": {"postcode": "75010"}},
                    {{"term": {city": "Paris"}},
                    {{"match": {"street": "rue des"}}
            ]    
        }
     },
     "aggs": {
        "street_agg": {
            "terms": {
                "field": "street",
                "size": 10
             }
         }           
     }
}

Проблема заключается в том, что она автоматическиотсортировано не по количеству баллов, а по количеству документов в каждом пакете.

Я бы хотел отсортировать сегменты по количеству произвольных документов, выбранных в каждом пакете (да, достаточночтобы получить оценку из одного документа в ведре, поскольку в моем примере оценка зависит только от содержимого поля улицы).

Как бы вы достигли этого?

1 Ответ

0 голосов
/ 04 июня 2018

Хорошо, таким образом, решение может быть найдено в Порядок агрегации Elasticsearch по наибольшему количеству попаданий , но только если вы прочитаете комментарий здесь от Shadocko: Порядок агрегации Elasticsearch по верхнему рейтингу попаданий , чего у меня не было.

Итак, вот решение для всех, кто заинтересован, и для моего будущего я:

{                                 
    'query': {
        'bool': {
            'must': [
                {'term': {'postcode': '75010'}},
                {'term': {'city': 'Paris'}},
                {'match': {'street.autocomplete': 'rue des'}}
            ]
         }
    },
    'aggs': {
        'street_agg': {
            'terms': {
                'field': 'street',
                'size': 10,
                'order': {
                    'max_score': 'desc'
                }
            },
            'aggs': {
                'max_score': {
                    'max': {'script': '_score'}
                }
            }
        }
    }
}

Это не идеально, так как оно использует функцию агрегирования max,это означает, что он делает ненужные вычисления (достаточно было просто взять один документ из корзины).Но, похоже, функции агрегации «выбрать один» нет, просто min, max, avg и sum, так что вам нужно это сделать.Ну, я думаю, что вычисление максимума не так уж и дорого.

...