Elasticsearch批量插入数据时snowball分词器搜索结果不正确问题
按发生概率从高到低排列如下:
批量导入后未主动刷新索引
如果为了提升bulk导入性能,你在导入前将索引的refresh_interval参数设置为-1(关闭自动刷新),导入完成后没有主动调用POST /test_index_version_1/_refresh接口,写入的文档就不会进入搜索可见的段,导致查询不到结果。
手动插入测试数据的场景中,单条文档写入默认会触发自动刷新,也会让索引的刷新逻辑恢复为默认1秒间隔,后续bulk写入的数据会在触发刷新后可见,因此查询结果符合预期。索引未创建完成就发起bulk请求
在Kibana执行完索引创建语句后,未等待集群返回创建成功响应、索引状态变为yellow/green就直接发起bulk导入,此时ES会判定目标索引不存在,按照默认规则自动创建索引。自动生成的索引没有你自定义的snowball词干分析器,workDesc字段会使用默认的standard分析器,无法对work的不同形态做词干归并,因此搜索working只能匹配到包含 exact 词working的文档,无法匹配其他变体。
手动插入测试数据的操作相当于验证了索引已经创建成功,后续导入的bulk数据会使用你自定义的mapping和分析器,因此查询正常。bulk请求字段名与mapping定义不一致
Elasticsearch字段名大小写敏感,如果SQL Server导出的字段名为全小写workdesc或存在其他拼写差异,bulk导入时未做字段名映射,会导致数据写入到ES自动生成的新字段中,你自定义的workDesc字段没有对应值,自然查询不到结果。
手动插入测试数据后再执行bulk时,查询返回的结果实际是手动写入的符合字段名要求的文档,容易误以为bulk导入的数据也被正确匹配。bulk请求格式错误导致数据写入失败
bulk API对请求格式有严格要求,每行必须为合法JSON且用换行分隔,若批量导入的请求存在格式错误,会导致部分或全部文档写入失败,你误以为数据导入成功实际未写入ES。手动插入的测试数据写入成功,因此查询能返回正确结果,容易造成bulk数据被正常检索的错觉。
你可以按以下步骤定位具体原因:
- 执行
GET /test_index_version_1/_mapping,确认workDesc字段的分析器配置是否符合预期,排除自动建索引的问题。 - 执行
GET /test_index_version_1/_count,确认索引内的文档数量是否和预期导入的数量一致,排除写入失败的问题。 - 执行
POST /test_index_version_1/_refresh后重新执行查询,如果能返回正确结果则确认是刷新策略的问题。 - 随机取一条bulk导入的文档ID,执行
GET /test_index_version_1/_doc/[文档ID],确认workDesc字段是否存在且值正确,排除字段名映射错误的问题。
内容的提问来源于stack exchange,提问作者ankur patel

