Elasticsearch агрегации поплавкового типа потери точности - PullRequest
0 голосов
/ 25 апреля 2019

Если вы используете Elasticsearch 5.5 с динамическим отображением поля и используете двойные значения.Эти значения получают тип float, когда я проверяю сопоставления.Когда вы используете агрегирование, ключ в корзинах будет терять точность.Значение 0.62 будет что-то вроде 0.6200000047683716.

Фрагмент кода

 "aggregations": {
    "float_numbers": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": 0.6200000047683716,
          "doc_count": 1
        }
      ]
    }
  }

Здесь описана та же проблема. ссылка

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

Решение состоит в том, чтобы сделать поплавок двойным.Этого можно добиться с помощью динамических шаблонов.

динамические шаблоны

динамическое отображение полей

Пример решения:

Добавить dynamic_templates в индекс пока нет ни одного товара.

PUT term-test
{
  "mappings": {
    "demo_typ": {
      "dynamic_templates": [
        {
          "all_to_double": {
            "match_mapping_type": "double",
            "mapping": {
              "type": "double"
            }
          }
        }
      ]
    }
  }
}

Добавление данных

POST term-test/demo_typ
{
  "numeric_field": 0.62,
  "long_filed": 44
}

Проверка сопоставления

GET term-test/_mapping

Выполнение агрегации

GET term-test/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "float_numbers": {
      "terms": {
        "field": "numeric_field"
      }
    }
  }
}

В Java Api выможет сделать следующее

1: сначала создать индекс

elasticClient.admin()
                .indices()
                .prepareCreate(indexName)
                .execute()
                .actionGet();

2: обновить отображение

JSON

{
  "dynamic_templates": [
    {
      "all_to_double": {
        "match_mapping_type": "double",
        "mapping": {
          "type": "double"
        }
      }
    }
  ]
}

Jsonв XContentBuilder я получил код от ссылка

 public XContentBuilder getXContentBuilderFromJson(final String json) {
        try {
            Map<String, Object> map = new ObjectMapper().readValue(json, new TypeReference<Map<String, Object>>() {});
            return XContentFactory.jsonBuilder().map(map);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

Обновление сопоставления

elasticClient.admin().indices()
.preparePutMapping(indexName)
.setType(yourType)
.setSource(getXContentBuilderFromJson(json))
.execute()
.actionGet();

3: вставить данные

...