Обновите все документы elasticsearch, используя dict для ввода с помощью Python.
У меня есть вариант использования, когда мне нужно обновить все документы elasticsearch. В моем индексе у меня есть источник, который выглядит примерно так:
{'_source': {
'employee_ids': ['J1234', 'J28373', 'CH1234', 'J98823', 'J1234'],
'non_employee_ids': [],
'friends_id': ['CH1234', 'J98823', 'J28373', 'H82739', 'J98823'],
'local_date': '2022/01/10',
'local': True
}
Каждый день я получаю новый список employee_id и связанных с ними друзей. Это при условии, что ничего не нужно решать. Полученные данные похожи на словарь python или объект json, где ключами являются old_ids, а значениями — new_ids. Такие как
{'J1234': 'J2875', 'CH1234': 'J2879'}
Я написал безболезненный скрипт для обновления идентификаторов, однако он требует цикла for для каждого списка, который мы хотим обновить. Это может быть выполнено через UpdateByQuery в
elasticsearch_dsl
библиотека.
def result = [];
for (def item: ctx._source.employee_ids)
{
if (item == params.fromId) {
gal_res.add(params.toId)
}
else {
gal_res.add(item)
}} ctx._source.employee_ids= result;
def resultF = [];
for (def item: ctx._source.friends_id)
{
if (item == params.fromId) {
gal_res.add(params.toId)
}
else {
gal_res.add(item)
}} ctx._source.friends_id = resultF ;
Вопросы. Есть ли более необязательное решение для обновления всех документов и списков полей без необходимости перебирать словарь Python один за другим, чтобы обновить все документы, соответствующие этому единственному идентификатору сотрудника?
Есть ли способ отправить словарь, чтобы найти все документы, соответствующие ключам, а затем обновить значения? В одной команде?
1 ответ
Готового решения для этого нет.
Одним из улучшений существующего безболезненного сценария является изменение массива на месте при использовании карты в параметрах, сопровождаемой списком полей для обновления.
PUT /test_replace_id/
{
"mappings": {
"properties": {
"employee_ids":{
"type": "keyword"
}
}
}
}
POST /test_replace_id/_doc/1
{
"employee_ids": ["old1","old2"],
"frieds_id": "old1"
}
POST /test_replace_id/_update/1
{
"script": {
"source": """
for (t in params.targets){
if (ctx._source[t] instanceof List){
for (int j=0; j<ctx._source[t].length; j++){
if (params.map.containsKey(ctx._source[t][j])) {
ctx._source[t][j] = params.map.get(ctx._source[t][j])
}
}
}else{
if (params.map.containsKey(ctx._source[t])) {
ctx._source[t] = params.map.get(ctx._source[t])
}
}
}
""",
"params":{
"targets": ["employee_ids","frieds_id"],
"map": {"old1":"new1"}
}
}
}
GET /test_replace_id/_search
Это обеспечивает большую гибкость и не требует повторения и обновления. Теперь мы можем отправить весь запрос сразу.
@Tomo_M за решение!