使用NEST为Elasticsearch同文档批量添加嵌套对象遇问题求助
向Elasticsearch嵌套字段批量追加30万条数据的正确实现
索引映射
{ "properties": { "allSubjects": { "type": "nested", "properties": { "nuis": { "type": "text", "fields": { "keyword": { "ignore_above": 256.0, "type": "keyword" } } }, "dateOfInspection": { "type": "date" } } }, "iD": { "type": "keyword" } } }
遇到的问题
- 直接向同一份文档存入30万条嵌套对象时,返回413错误(请求实体过大)
- 将数据拆分为每批1万条后,使用
IndexDocument方法会覆盖之前批次的数据,因为该操作是全量替换文档,而非追加内容
正确实现方式
要实现嵌套数组的批量追加,需使用Elasticsearch的Update API,通过脚本(Script)将新批次的嵌套对象追加到已有数组中,而非全量替换文档。以下是修正后的C#代码:
public bool AddToElasticObjectsBulk(SobElastic sobElastic) { var chunks = sobElastic.AllObjects.Chunk(10000).ToList(); var indexName = "my-obj"; var documentId = sobElastic.ID; // 第一步:创建初始文档(包含第一批数据) var initialResponse = _elasticClient.Index(new SobElastic { ID = documentId, AllObjects = chunks[0].ToList() }, d => d.Index(indexName)); if (!initialResponse.IsValid) { // 处理初始创建失败的情况 return false; } // 后续批次:通过Update API追加数据 for (int i = 1; i < chunks.Count; i++) { var batch = chunks[i].ToList(); var updateResponse = _elasticClient.Update<SobElastic, object>(documentId, u => u .Index(indexName) .Script(s => s .Inline("ctx._source.allSubjects.addAll(params.newSubjects)") .Params(p => p.Add("newSubjects", batch)) ) .RetryOnConflict(3) // 处理并发更新冲突 ); if (!updateResponse.IsValid) { // 处理单批次更新失败的情况,可根据需求添加重试或日志 return false; } } return true; }
关键说明
- 使用
Update方法而非IndexDocument:Update操作针对现有文档进行增量修改,不会覆盖原有数据 - 脚本逻辑:通过
ctx._source.allSubjects.addAll(params.newSubjects)将新批次的嵌套对象追加到数组末尾 - 冲突重试:添加
RetryOnConflict(3)参数,避免并发更新时出现版本冲突报错
内容的提问来源于stack exchange,提问作者clayon_jo
相关产品推荐
相关产品推荐

