Elasticsearch, разбивающий на страницы отсортированный агрегированный результат - PullRequest
0 голосов
/ 18 февраля 2019

Насколько я знаю, в Elasticsearch нет способа сделать что-то вроде следующего:

SELECT * FROM myindex
GROUP BY agg_field1, agg_field2, agg_field3 // aggregation
ORDER BY order_field1, order_field2, order_field3 // sort
LIMIT 1000, 5000 // paginate -- get page 6 of size 1000 records

Вот несколько связанных с этим документов относительно этого:

Есть ли способ сделать вышеперечисленное в Elasticsearch?Единственное ограничение, которое у нас есть, это то, что у нас никогда не будет более 10 миллионов записей, поэтому мы (надеюсь) не должны сталкиваться с ошибками памяти.Я думал сделать это следующим образом:

  • Выполнить запрос агрегации
  • Получить количество результатов из него
  • Разделить его на N сегментов на основе результатови размер страницы, который мы хотим
  • Повторите запрос с указанными выше сегментами

Каков наилучший способ сделать это?В своем ответе / предложении, не могли бы вы опубликовать пример кода, касающегося того, как вышеуказанный SQL-запрос может быть выполнен в ES?:

# 5.6
e=Elasticsearch('https://search-testinges-fekocjpedql2f3rneuagyukvy4.us-west-1.es.amazonaws.com')
e.search('testindex')

# 6.4 (same data as above)
e = Elasticsearch('https://search-testinges6-fycj5kjd7l5uyo6npycuashch4.us-west-1.es.amazonaws.com')
e.search('testindex6')

Имеет 10 000 записей.Не стесняйтесь тестировать с ним:

enter image description here

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

SELECT * FROM testindex
GROUP BY store_url, status, title
ORDER BY title ASC, status DESC
LIMIT 100 OFFSET 6000

Другими словами, я хочу отсортировать агрегированный результат (с несколькими агрегациями) и получить смещение.

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Здесь может помочь composite агрегация , поскольку она позволяет группировать по нескольким полям и разбивать результаты на страницы.Единственное, что он не позволяет вам сделать, - это перейти с заданным смещением, но вы можете сделать это, перебирая код своего клиента, если это вообще необходимо.

Так вот пример запроса для этого:

POST testindex6/_search
{
  "size": 0,
  "aggs": {
    "my_buckets": {
      "composite": {
        "size": 100,
        "sources": [
          {
            "store": {
              "terms": {
                "field": "store_url"
              }
            }
          },
          {
            "status": {
              "terms": {
                "field": "status",
                "order": "desc"
              }
            }
          },
          {
            "title": {
              "terms": {
                "field": "title",
                "order": "asc"
              }
            }
          }
        ]
      },
      "aggs": {
        "hits": {
          "top_hits": {
            "size": 100
          }
        }
      }
    }
  }
}

В ответе вы увидите и after_key структуру:

  "after_key": {
    "store": "http://google.com1087",
    "status": "OK1087",
    "title": "Titanic1087"
  },

Это какой-то курсор, который вам нужно использовать в ваших последующих запросах, например так:

{
  "size": 0,
  "aggs": {
    "my_buckets": {
      "composite": {
        "size": 100,
        "sources": [
          {
            "store": {
              "terms": {
                "field": "store_url"
              }
            }
          },
          {
            "status": {
              "terms": {
                "field": "status",
                "order": "desc"
              }
            }
          },
          {
            "title": {
              "terms": {
                "field": "title",
                "order": "asc"
              }
            }
          }
        ],
        "after": {
          "store": "http://google.com1087",
          "status": "OK1087",
          "title": "Titanic1087"
        }
      },
      "aggs": {
        "hits": {
          "top_hits": {
            "size": 100
          }
        }
      }
    }
  }
}

И это даст вам следующие 100 ведер.Надеюсь, это поможет.

ОБНОВЛЕНИЕ :

Если вы хотите узнать, сколько будет общее количество сегментов, агрегация composite не даст вамэтот номер.Однако, поскольку агрегация composite является не чем иным, как декартовым произведением всех полей в ее источниках, вы можете получить хорошее приближение к этому общему числу, также возвращая] количество элементов] (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html) каждого поляиспользуется в агрегации composite и умножении их вместе.

  "aggs": {
    "my_buckets": {
      "composite": {
        ...
      }
    },
    "store_cardinality": {
      "cardinality": {
        "field": "store_url"
      }
    },
    "status_cardinality": {
      "cardinality": {
        "field": "status"
      }
    },
    "title_cardinality": {
      "cardinality": {
        "field": "title"
      }
    }
  }

Затем мы можем получить общее количество сегментов, умножив число, которое мы получаем в store_cardinality, status_cardinality и title_cardinality вместе,или, по крайней мере, хорошего приближения к нему (это не будет хорошо работать на полях с большим количеством элементов, но довольно хорошо на полях с низким количеством элементов).

0 голосов
/ 19 февраля 2019

Свертывание полей - это ответ.

Функция свертывания полей используется, когда мы хотим сгруппировать попадания по определенному полю (как в группе по agg_field).

До Elastic 6 способ группировки полей состоит в том, чтобы использовать агрегирование .У этого подхода не было возможности сделать эффективный пейджинг.

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

Ниже приведен пример запроса со сверткой поля, взятой из приведенной выше ссылки.

GET /twitter/_search
{
  "query": {
      "match": {
          "message": "elasticsearch"
      }
  },
  "collapse" : {
      "field" : "user", 
      "inner_hits": {
          "name": "last_tweets", 
          "size": 5, 
          "sort": [{ "date": "asc" }] 
      },
      "max_concurrent_group_searches": 4 
  },
  "sort": ["likes"]

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...