Node.js中Elasticsearch实现emp及empTrans字段upsert的正确方法
Node.js 环境 Elasticsearch emp/empTrans 字段 upsert 实现方案
现有代码错误原因
- 字段名匹配错误:你需要操作
emp数组,但脚本中写的是ctx._source.comments.add,comments字段不存在,导致更新逻辑没有命中目标字段 - 缺少边界判断:如果目标文档存在但
emp字段未初始化,直接调用add方法会触发运行时异常,更新失败 - 无upsert配置:没有配置文档不存在时的初始化逻辑,无法实现「不存在则新增、存在则更新」的upsert效果
正确实现代码
场景1:emp数组追加新元素 + 同步更新empTrans字段(支持upsert)
const result = await client.update({ index: 'test', // Elasticsearch 7.x及以上版本无需配置type参数,废弃type后可以删除下面这行 type: 'emp', id: '1', // 你的文档主键id body: { // 脚本:存在文档时执行的更新逻辑 script: { inline: ` // 初始化emp数组 if (ctx._source.emp == null) { ctx._source.emp = [] } // 追加新的emp元素 ctx._source.emp.add(params.emp) // 更新empTrans字段 ctx._source.empTrans = params.empTrans `, params: { emp: { empId: 'xyz1234', empDetail: { name: 'ss' } }, empTrans: { date: '2024-01-01' // 你要更新的empTrans值 } } }, // upsert配置:文档不存在时,直接插入该内容作为初始文档 upsert: { id: '1', emp: [ { empId: 'xyz1234', empDetail: { name: 'ss' } } ], empTrans: { date: '2024-01-01' } } } })
场景2:更新emp数组中指定empId的元素(不存在则追加)
如果你的需求不是追加元素,而是修改已有empId对应的员工信息,可以用下面的脚本替换上面的inline部分:
inline: ` if (ctx._source.emp == null) { ctx._source.emp = [] } // 查找匹配empId的元素下标 def empIndex = ctx._source.emp.findIndex(item -> item.empId == params.emp.empId) if (empIndex >= 0) { // 存在则更新 ctx._source.emp[empIndex] = params.emp } else { // 不存在则追加 ctx._source.emp.add(params.emp) } ctx._source.empTrans = params.empTrans `
注意事项
- 高版本Elasticsearch(7.x+)已经移除了type的支持,对应参数直接删除即可,无需填写
- 如果更新执行报错,可先检查对应索引的mapping配置,确认emp字段类型为Array、empTrans为Object类型
- 批量更新场景建议使用
client.bulk接口提升性能
内容的提问来源于stack exchange,提问作者Dharmendra Singh
相关产品推荐
相关产品推荐

