首页 > 解决方案 > 如何将特殊格式的数据导入 Elasticsearch?

问题描述

我收到了一个 15 GB 的 .txt 文件,其格式如下:

{
  "_score": 1.0,
  "_index": "newsvit",
  "_source": {
    "content": " \u0641\u0647\u06cc\u0645\u0647 \u062d\u0633\u0646\u200c\u0645\u06cc\u0631\u06cc:  ",
    "title": "\u06a9\u0627\u0631\u0647\u0627\u06cc \u0642\u0627\u0644\u06cc\u0628\u0627\u0641 ",
    "lead": "\u062c\u0627\u0645\u0639\u0647 > \u0634\u0647\u0631\u06cc - 
    \u0645\u06cc\u0632\u06af\u0631\u062f\u06cc \u062f\u0631\u0628\u0627\u0631\u0647 .",
    "agency": "13",
    "date_created": 1494518193,
    "url": "http://www.khabaronline.ir/(X(1)S(bud4wg3ebzbxv51mj45iwjtp))/detail/663749/society/urban",
    "image": "uploads/2017/05/11/1589793661.jpg",
    "category": "15"
  },
  "_type": "news",
  "_id": "2981643"
}
{
  "_score": 1.0,
  "_index": "newsvit",
  "_source": {
    "content": "\u0645/\u0630",
    "title": "\u0645\u0639\u0646\u0648\u06cc\u062a \u062f\u0631 \u0639\u0635\u0631 ",
    "lead": "\u0645\u062f\u06cc\u0631 \u0645\u0624\u0633\u0633\u0647 \u0639\u0644\u0645\u06cc \u0648 \u067e\u0698\u0648\u0647\u0634\u06cc \u0627\u0628\u0646\u200c\u0633\u06cc\u0646\u0627 \u062f\u0631 .",
    "agency": "1",
    "date_created": 1494521817,
    "url": "http://www.farsnews.com/13960221001386",
    "image": "uploads/2017/05/11/1713799235.jpg",
    "category": "20"
  },
  "_type": "news",
  "_id": "2981951"
}
....

我想将它导入elasticsearch。我尝试过 BulkAPI,但由于它只接受特定样式的 JSON,我无法将整个 15 GB 文件转换为 Bulk 格式。我也尝试过logstash,但是像这样的字段content将无法搜索和查询。

将此文件导入elasticsearch的最有效方法是什么?

标签: jsonelasticsearch

解决方案


首先,这似乎是从名为news. 因此,如果您仍然可以访问/可以访问该索引,则可以从远程集群重新索引到您自己的。


话虽如此,我建议编写一个脚本(例如在 python 中,也可以是 bash)将其转换为 json。您的文件已经几乎像 json - 它只是缺少包装括号[{}, {}, {}]和分隔各个对象的逗号。

您可以很容易地预先[添加和附加]到任何文本文件。或者,也有文本编辑器可以神奇地打开如此大的文件——对于 Mac,例如HexFiend。也可能有一个Windows替代品。

完成后,您可以编写一个脚本来通过正则表达式拆分文本文件,例如/^\}$/gm--testable here。拆分后,您可以使用逗号字符将其重新加入,,然后

  1. 另存为.json,然后使用批量@data-binary选项
  2. 或者使用批量 DSL API——在 python 中再次举例

开始使用 python 加载器脚本:

import json
import re

# load the large text file 
text_str = '...'


my_json_list = map(json.loads,
             # ^^^ iterate & convert to a python dict all objects
                   [
                       # that are contained in the split list
                       lineitem for lineitem in re.split(
                           # by replacing '\n'
                           "\n",
                           # that we introduced after replacing the
                           # current object separators, i.e. '}{' with '\n'
                           re.sub(r'}{', '}\n{',
                                  # after getting rid of the original
                                  # line-breaks
                                  re.sub(r'\n', '', text_str)))
                   ]
            )

推荐阅读