巨大なJSONをSolrに投入する

今回は小ネタです。

先日、1GB近くある巨大なJSONファイルをSolrに投入する機会がありました。とあるシステムからダンプしたデータで、以下のような形になっています。

[{"id":"10001","name":"名前1","description":"説明文1","timestamp":"2018-01-01 12:00:00"},{"id":"10002","name":"名前2","description":"説明文2","timestamp":"2018-01-02 12:00:00"},{"id":"10003","name":"名前3","description":"説明文3","timestamp":"2018-01-03 12:00:00"},{"id":"10004","name":"名前4","description":"説明文4","timestamp":"2018-01-04 12:00:00"},{"id":"10005","name":"名前5","description":"説明文5","timestamp":"2018-01-05 12:00:00"},...]

要するに、改行のない巨大な1行のテキストファイルです。
SolrにJSONファイルをPOSTしてインデックスを作成させることはできますが、1GBはちょっと大きすぎるので、分割することを考えました。

1行1レコードになっていれば話は簡単で、適当な行数で分割してからJSONの配列になるように加工すればいいだけのことですが、全部が1行になっているのでそういう訳にはいきません。

スクリプト言語でJSONを読み込んで分割することも考えましたが、JSON全体を一括で読み込んで処理するタイプのJSONパーサーでは1GBを扱うのは辛いものがあります。SAXタイプのJSONパーサーを探さないといけないかなあと考えているうちに、jq コマンドを使うのがいいんじゃないかと思い当たりました。

$ jq '.[]' sample.json
{
  "id": "10001",
  "name": "名前1",
  "description": "説明文1",
  "timestamp": "2018-01-01 12:00:00"
}
{
  "id": "10002",
  "name": "名前2",
  "description": "説明文2",
  "timestamp": "2018-01-02 12:00:00"
}
{
  "id": "10003",
  "name": "名前3",
  "description": "説明文3",
  "timestamp": "2018-01-03 12:00:00"
}
{
  "id": "10004",
  "name": "名前4",
  "description": "説明文4",
  "timestamp": "2018-01-04 12:00:00"
}
{
  "id": "10005",
  "name": "名前5",
  "description": "説明文5",
  "timestamp": "2018-01-05 12:00:00"
}

一番外の配列を外して各レコードを取り出すことはできました。1レコード1行になっていると加工しやすいので-cオプションを指定します。

$ jq -c '.[]' sample.json
{"id":"10001","name":"名前1","description":"説明文1","timestamp":"2018-01-01 12:00:00"}
{"id":"10002","name":"名前2","description":"説明文2","timestamp":"2018-01-02 12:00:00"}
{"id":"10003","name":"名前3","description":"説明文3","timestamp":"2018-01-03 12:00:00"}
{"id":"10004","name":"名前4","description":"説明文4","timestamp":"2018-01-04 12:00:00"}
{"id":"10005","name":"名前5","description":"説明文5","timestamp":"2018-01-05 12:00:00"}

ここまでくれば後は簡単で、1000行程度ずつ読み込んでまとめてPOSTするスクリプトを作成して無事に投入することができました。

コメント