方法

使用 elasticdump 可以从 json 导入 es。首先,npm 全局安装 elasticdump

假设 json 文件是对象数组格式

[
    {"key1": "value1", "key2": "value2"},
    {"key1": "value1", "key2": "value2"},
    {"key1": "value1", "key2": "value2"},
    {"key1": "value1", "key2": "value2"}
]

直接使用 elasticdump 命令是无法导入成功的,必须转换为以下格式:

{"_source": {"key1": "value1", "key2": "value2"}}
{"_source": {"key1": "value1", "key2": "value2"}}
{"_source": {"key1": "value1", "key2": "value2"}}
{"_source": {"key1": "value1", "key2": "value2"}}
{"_source": {"key1": "value1", "key2": "value2"}}

然后执行命令

elasticdump --input=./ESdata.json --output=http://localhost:9200/索引/类型 --type=data

就可以了

代码工具

为方便以后类似操作,自己写了三个脚本工具,自动完成繁琐的格式处理和数据导入

json 同一目录下新建三个文件

index.js

const fs = require('fs')

const iFile = process.argv[2]
const oFile = `ES${iFile}`

async function main() {
    var objArr = JSON.parse(await readLargeFileSync(iFile, 'utf8'))
    var arr = objArr.map(obj => {
        var o = {}
        // obj.数字字段 = +obj.数字字段
        o["_source"] = obj
        return JSON.stringify(o)
    })

    var str = arr.join('\n')

    try {
        fs.writeFileSync(oFile, str)
    } catch(e) {
        console.log(e)
    }
}

// 定义这个函数是因为 readFileSync 读大文件时遇到内存的 bug
async function readLargeFileSync(filename, encoding) {
    return new Promise((resolve, reject) => {
        var data = ''

        var readerStream = fs.createReadStream(filename)
        readerStream.setEncoding(encoding)

        readerStream.on('data', function(chunk) {
            data += chunk
        })

        readerStream.on('end',function(){
            resolve(data)
        })
    })
}

main()

transform.bat

@echo off
node --max-old-space-size=25600 index.js %~nx1
echo 数据转换完成!
pause

注意:这里 --max-old-space-size=25600 意思是给 node 设置 20G (20 * 1024) 的内存,所以这里内存应该根据实际电脑参数设置

import.sh

#!/bin/bash

starttime=`date +'%Y-%m-%d %H:%M:%S'`
elasticdump --input=./ESdata1.json --output=http://localhost:9200/bilibili/videoMsg --type=data
endtime=`date +'%Y-%m-%d %H:%M:%S'`
start_seconds=$(date --date="$starttime" +%s);
end_seconds=$(date --date="$endtime" +%s);
echo "本次运行时间: "$((end_seconds-start_seconds))"s"
# read -p "Press any key to continue." var

starttime=`date +'%Y-%m-%d %H:%M:%S'`
elasticdump --input=./ESdata2.json --output=http://localhost:9200/bilibili/videoMsg --type=data
endtime=`date +'%Y-%m-%d %H:%M:%S'`
start_seconds=$(date --date="$starttime" +%s);
end_seconds=$(date --date="$endtime" +%s);
echo "本次运行时间: "$((end_seconds-start_seconds))"s"
# read -p "Press any key to continue." var

......

注意:这里 # read -p ... 这一行是注释,取消注释会使得执行该文件后每次导入完成一个文件会暂停

使用方法:

  • 把 json 文件拖进 transform.bat,一会儿自动生成加 es 前缀的可导入 json 文件
  • 修改 import.sh 的 json 文件名,双击执行多文件导入

此外,希望进一步了解将本地 es 导入服务器 es 的后续操作,可以参考这里