现在有这么一个需求:
近1T的JSON文件,每份文件的字段不一定完全相同。
【大约5亿条数据,测试了下,在设置为
"number_of_shards": 5,
】时,140万条数据耗时9分40秒,太差劲了。TODO:优化
"number_of_replicas": 2
对于一个索引来说,number_of_shards只能设置一次,而number_of_replicas可以使用索引更新设置API在任何时候被增加或者减少。
1.最初的思路是:
- 先直接使用_bulk API导入ES,
- 借鉴自动导入的mapping,修改mapping
- 再次导入
2.结果使用_bulk API导入ES时报错:
curl -H 'Content-Type: application/x-ndjson' -XPOST '172.21.******:9200/mapper_/automatic_/_bulk?pretty' --data-binary @mag_papers_0.json
"type" : "illegal_argument_exception",
"reason" : "Malformed action/metadata line [1], expected START_OBJECT or END _OBJECT but found [VALUE_STRING]"
},
"status" : 400
错误原因:
_bulk API导入ES的JSON文件需要满足一定的格式,每条记录之前,需要有文档ID且每一行\n结束
这里有相同问题的讨论
大致讨论结果,两条思路:
- 使用logstash
- 老实加上ID
暂时采用老实加ID方法:
- 批量读取文件
- 每一条Json文档都加上ID
- 与上次实践不同的是,这里有必要开启”嗅探“模式,动态加入节点。允许从运行的Elasticsearch集群自动发现节点并将它们设置为现有RestClient实例
只需要指定集群中的某一个节点(不一定是主节点)
先导部分数据,查看使用自动生成mapping
public class JsonToES {
private static final Logger LOGGER = LoggerFactory.getLogger(OpenClose.class);
public void jsonToES(File[] files) {
Map<String, Object> hashMap = EsPropertiesUtils.getConf();
TransportClient client = OpenClose.getInstance(hashMap);
int idNum = 0;
for (File f : files) {
// 一、绝对路径读取文件
System.out.println(f.getAbsolutePath());