Elasticsearch безболезненно обновляет список уникальных элементов
РЕДАКТИРОВАТЬ:
Моя проблема была вызвана ";" в конце строки, о чем я мог догадаться, прочитав полное сообщение об ошибке:
'error': {
'type': 'illegal_argument_exception',
'reason': 'failed to execute script',
'caused_by': {
'type': 'script_exception',
'reason': 'compile error',
'script_stack': ['... dd(params.collected_via)};
ctx ..., ^---- HERE'],
'caused_by': {
'type': 'illegal_argument_exception',
'reason': "unexpected token [';'] was expecting one of [<EOF>]."
}
}
}
Я исправил это, переключив 2 строки в моем третьем скриптовом решении:
"script": {
"source": "ctx._source.internal_count = params.internal_count; \
if (!ctx._source.collected_via.contains(params.collected_via)) { ctx._source.collected_via.add(params.collected_via) }",
"lang": "painless",
"params": {
"collected_via": my_tag,
"internal_count": my_count
}
================================================== ===================
ОРИГИНАЛЬНЫЙ ВОПРОС:
Поле "collection_via" в нашем индексе elasticsearch (6.8) представляет собой список тегов. При обновлении документов список тегов обновляется с помощью следующего скрипта:
"script": {
"source": "ctx._source.collected_via.add(params.collected_via); \
ctx._source.internal_count = params.internal_count",
"lang": "painless",
"params": {
"collected_via": my_tag,
"internal_count": my_count
}
Как преобразовать этот скрипт, чтобы каждый тег добавлялся в список только один раз? Вот решения, которые я пробовал и которые не работают ("причина": "не удалось выполнить скрипт"):
"script": {
"source": "if (ctx._source.collected_via.contains(params.collected_via)) {} { ctx._source.collected_via.add(params.collected_via) }; \
ctx._source.internal_count = params.internal_count",
"lang": "painless",
"params": {
"collected_via": my_tag,
"internal_count": my_count
}
"script": {
"source": "ctx._source.collected_via = ctx._source.collected_via.add(params.collected_via).unique(); \
ctx._source.internal_count = params.internal_count",
"lang": "painless",
"params": {
"collected_via": my_tag,
"internal_count": my_count
}
"script": {
"source": "if (!ctx._source.collected_via.contains(params.collected_via)) { ctx._source.collected_via.add(params.collected_via) }; \
ctx._source.internal_count = params.internal_count",
"lang": "painless",
"params": {
"collected_via": my_tag,
"internal_count": my_count
}
1 ответ
Математика спешит на помощь! Лучший способ добиться этого - просто использовать Set, который по определению всегда будет содержать только одно вхождение данного элемента.
// 1. create a set out of the current list
def set = new HashSet(ctx._source.collected_via);
// 2. add all new elements to the set
set.add(params.collected_via);
// 3. convert the set back to a list
ctx._source.collected_via = new ArrayList(set);