Elasticsearch - Как получить список популярных слов

У меня есть временный индекс с документами, которые мне нужно смягчить. Я хочу сгруппировать эти документы с помощью слов, которые они содержат.

Например, у меня есть эти документы:

1 - "aaa bbb ccc ddd eee fff"

2 - "bbb mmm aaa fff xxx"

3 - "hhh aaa fff"

Итак, я хочу получить самые популярные слова, в идеале с графами: "aaa" - 3, "fff" - 3, "bbb" - 2 и т.д.

Возможно ли это с помощью elasticsearch?

Ответ 1

Выполнение простого поиска агрегации по срокам удовлетворит ваши потребности:

(где mydata - имя вашего поля)

curl -XGET 'http://localhost:9200/test/data/_search?search_type=count&pretty' -d '{
  "query": {
    "match_all" : {}
  },
  "aggs" : {
      "mydata_agg" : {
    "terms": {"field" : "mydata"}
    }
  }
}'

вернется:

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "mydata_agg" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [ {
        "key" : "aaa",
        "doc_count" : 3
      }, {
        "key" : "fff",
        "doc_count" : 3
      }, {
        "key" : "bbb",
        "doc_count" : 2
      }, {
        "key" : "ccc",
        "doc_count" : 1
      }, {
        "key" : "ddd",
        "doc_count" : 1
      }, {
        "key" : "eee",
        "doc_count" : 1
      }, {
        "key" : "hhh",
        "doc_count" : 1
      }, {
        "key" : "mmm",
        "doc_count" : 1
      }, {
        "key" : "xxx",
        "doc_count" : 1
      } ]
    }
  }
}

Ответ 2

Возможно, потому, что этому вопросу и принятому ответу уже несколько лет, но теперь есть лучший способ.

Принятый ответ не принимает во внимание тот факт, что наиболее распространенные слова обычно неинтересны, например, такие слова, как "the", "a", "in", "for" и так далее.

Обычно это относится к полям, которые содержат данные типа text а не keyword.

Вот почему ElasticSearch на самом деле имеет агрегацию специально для этой цели, называемую "Сводная агрегация текста".
Из документов:

  • Он специально разработан для использования в text полях типа
  • Не требует полевых данных или значений документа
  • Он повторно анализирует текстовое содержимое на лету, что означает, что он также может отфильтровывать дубликаты зашумленного текста, которые в противном случае имеют тенденцию искажать статистику.

Однако это может занять больше времени, чем другие виды запросов, поэтому рекомендуется использовать его после фильтрации данных с помощью query.match или с предыдущей агрегацией типа sampler.

Итак, в вашем случае вы бы отправили запрос следующим образом (не включая фильтрацию/выборку):

{
    "aggs": {
        "keywords": {
            "significant_text": {
                "field": "myfield",
            }
        }
    }
}