#java #json #elasticsearch
#java #json #elasticsearch
Вопрос:
Это результат вложенного запроса агрегации ES. Мне нужно проанализировать этот ответ и преобразовать его в новый формат JSON. Из следующего JSON единственными полями, которые меня интересуют, являются значения key_as_a_string и значение яблок и апельсинов для каждого ключа.
"aggregations": {
"Inner_aggregation": {
"doc_count": 366,
"Hours_aggregation": {
"doc_count": 366,
"by_day": {
"buckets": [
{
"key_as_string": "2016-01-11",
"key": 1452556800000,
"doc_count": 1,
"Apples": {
"value": 5
},
"Oranges": {
"value": 3
}
},
{
"key_as_string": "2016-01-12",
"key": 1452556800000,
"doc_count": 1,
"Apples": {
"value": 43
},
"Oranges": {
"value": 2
}
},
.........,
.........
]
}
}
}
}
}
Я могу проанализировать его с помощью Jackson objectmapper или с помощью метода sr.getAggregations().get(«histogram_name»), а затем выполнить итерацию по коллекциям. Хотел узнать, есть ли простой способ.
Требуемый формат JSON
{
"Results": [{
"key_as_string": "2016-01-11",
"Apple_to_Orange_Ratio": 0.112
}, {
"key_as_string": "2016-01-12",
"Apple_to_Orange_Ratio": 0.12
}]
}
Соотношение будет найдено простым делением количества яблок и апельсинов.
Комментарии:
1. нет, это ответ интерфейса rest, поступающий из кластера, вы не можете изменить формат ответа. В этом весь смысл rest. Для перевода данных может потребоваться переводчик между вашим кластером и клиентом.
Ответ №1:
Когда ваше представление Java сильно отличается от сложной вложенной структуры, может оказаться бесполезным сопоставлять json непосредственно с классами Java. Вы могли бы обрабатывать такого рода данные динамически.
Вот способ обработки таких данных с использованием Java 8 и библиотеки Dynamics.
Мы анализируем json в структуру карты / списка и преобразуем это в динамический экземпляр
Map jsonMap = new ObjectMapper().readValue(exampleJson, Map.class);
Dynamic jsonData = Dynamic.from(jsonMap);
Это дает нам безопасный и удобный способ работы с этой вложенной структурой. В данном случае нас интересуют сегменты, и было бы неплохо легко добраться до них.
List<MyResult> results = jsonData
.dget("aggregations.Inner_aggregation.Hours_aggregation.by_day.buckets")
.children()
.map(bucket -> new MyResult(bucket))
.collect(toList());
Теперь наш класс myResult может обрабатывать данные корзины, которые также являются динамическим экземпляром.
public class MyResult {
private final Dynamic bucket;
public Result(Dynamic bucket) {
this.bucket = bucket;
}
public String getKey() {
return bucket.get("key_as_string").asString();
}
public double getAppleToOrangeRatio() {
double apples = bucket.dget("Apples.value").convert().intoDouble();
double oranges = bucket.dget("Oranges.value").convert().intoDouble();
return oranges / apples;
}
}
И мы можем получить доступ к соотношениям.
double appleToOrangeRatio = results.get(0).getAppleToOrangeRatio();
// 0.6
См. https://github.com/alexheretic/dynamics для получения источника, документации и примеров.