Добрый день!
Допустим, у нас есть следующий маппинг:
"tweet" : {
"properties" : {
"text" : {
"type" : "string"
},
"comments" : {
"type" : "object",
"properties" : {
"text" : {
"type" : "string"
},
"id" : {
"type" : "long"
}
}
}
}
}
и в индексе twitter есть документ с этим маппингом:
{
"text" : "sample text",
"comments" : []
}
Приведём аналогичные классы в Java:
class Comment {
String text;
Long id;
}
class Tweet {
String text;
Set<Comment> comments;
}
Теперь вопрос: как добавить очередной объект класса Comment в поле-массив comments? какой способ обновления этого поля является признанным сообществом?
Приведу варианты, рабочие и нет.
1. Рабочий вариант:
Map<String, Object> commentMap = new HashMap<String, Object>();
commentMap.put("text", comment.text);
client.update(new UpdateRequest("twitter", "tweet", "1")
.script("ctx._source.comments += p")
.addScriptParam("p", commentMap))
.actionGet();
3. Не рабочий:
client.update(new UpdateRequest("twitter", "tweet", "1")
.script("ctx._source.comments += p")
.addScriptParam("p", toJson(comment)))
.actionGet();
toJson() - функция, которая любой объект конвертирует в json-строку.
4. Не рабочий:
client.update(new UpdateRequest("twitter", "tweet", "1")
.script("ctx._source.comments += " + toJson(comment)))
.actionGet();
5. С помощью рефлексии можно разобрать объект comment, определить его поля и воспользоваться способом 1.
В чём проблема способа 1?
Недостаточный уровень абстракции:
1. если изменится класс Comment придётся менять метод;
2. для каждого другого такого класса нужно писать свою реализацию обновления.
Если есть альтернативы способу 5, буду рад их услышать.