Elasticsearchの検索結果をcsv形式で取得する

Elasticsearchの検索結果をcsvで取得できると良いのに、と思っていたところ、jqってコマンドがあるんですね。 Linux系のコマンドラインで利用できるコマンドで、jsonsedとかawkとかgrepみたいにできるやつらしいです。

公式サイトはこちら。

jq

こちらのサイトでは、マニュアルを日本語訳してくれています。

軽量JSONパーサー『jq』のドキュメント:『jq Manual』をざっくり日本語訳してみました | Developers.IO

まず、インストール方法は以下です。モジュールをダウンロードしてくるだけですね。

# wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 -O /usr/local/bin/jq
# chmod +x /usr/local/bin/jq
# jq --version
jq-1.5

実際にElasticsearchの検索結果をcsv形式にしてみます。 以下を参考しました。

ElasticsearchからデータをCSV形式でワンライナーで取り出す - Qiita

Is there any way in Elasticsearch to get results as CSV file in curl api? - Stack Overflow

例えば、以下のような検索結果の場合、

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "hits" : {
    "total" : 338,
    "max_score" : null,
    "hits" : [ {
      "_index" : "shikiho",
      "_type" : "shikiho",
      "_id" : "AVfXWNCJ3dgHhWAY7G81",
      "_score" : null,
      "_source" : {
        "code" : 2351,
        "creadtedDate" : "作成日:2016年09月16日",
        "meigaraName" : "2351 (株)ASJ  えいえすじぇい  [情報・通信業]",
        "url" : "【URL】 http://www.asj.ad.jp/",
        "accountingPeriod" : "【決算】3月",
        "establishmentDate" : "【設立】1984.2",
        "listingDate" : "【上場】2003.1",
        "feature" : "【特色】サーバーホスティング業界中堅。ネット予約・決済、ブラウザ野球ゲーム等に進出。M&A注力",
        "business" : "【連結事業】ネットサービス100 <16・3>",
        "assets" : "",
        "finance" : "",
        "nullColumn1" : "",
        "comment1" : "【買収効果】今年2月末のNTTデータERP子会社買収が通期寄与、年商10億円上乗せ。決済代行は柱の商議所向け簿記検定受付システムが終盤にかけ、積み上がる。のれん負担増 や開発費増埋め、営業益増。",
        "comment2" : "【取得】NTTデータERP子会社発行株の少数株主持分14・3%追加取得し、完全子会社化。同社製人事管理システムのクラウド対応急ぎ、本体とのシナジー追求。",
        "industryType" : "【業種】 通信サービス 時価総額順位  87/97社",
        "vendor" : "【仕入先】―",
        "customer" : "【販売先】―",
        "rival" : "【比較会社】3788 GMOクラ,4304 Eストアー,3633 GMOペパ",
        "headOffice" : "【本社】332-0017埼玉県川口市栄町3-2-16 TEL048-259-5111",
        "branchOffice" : "",
        "workerNumber" : "【従業員】<16.6>連171名 単61名(35.5歳)[年]524万円",
        "security" : "【証券】[上]東京(マ)[幹](主)SMBCフ(副)大和,日興,むさし,楽天,HS,松井[名]三菱U信[監]新日本",
        "bank" : "【銀行】三井住友,埼玉りそな,武蔵野,三菱U",
        "affiliate" : "【連結】イー・フュージョン,ASJコマース,アイテックス",
        "nullColumn2" : "",
        "progress" : "【四半期進捗率】3期平均7.9%* 今期-108%(-116%)",
        "holderNumber" : "2496"
      },
      "sort" : [ 2496 ]
    } ]
  }
}

取得したい値をフィルタリング指定します。 "code"の値を取得したい場合、"code"までのパスを指定してあげます。この場合、"hits" の"hits"の配列内の"_source"の"code"ですね。コマンドだとこんな感じです。

# curl -s -XPOST "http://localhost:9200/shikiho/shikiho/_search?pretty" -d @search.json | jq -cr ".hits.hits[]._source.code"
2351

csvで取得する方法ですが、jqコマンドには1アレイ内の各文字列をcsv形式で出力変換してくれる@csvというオプションがあるので、これを利用します。

まずはcsv出力の前段階として、以下のフィルタリングを与えたjqを実行してあげると、きれいに_sourceの値だけを、オブジェクト単位で抽出してくれてます。

# curl -s -XPOST "http://localhost:9200/shikiho/shikiho/_search?pretty" -d @search_test_bk.json | jq -r ".hits.hits[]._source"
{
  "code": 2351,
  "creadtedDate": "作成日:2016年09月16日",
  "meigaraName": "2351 (株)ASJ  えいえすじぇい  [情報・通信業]",
  "url": "【URL】 http://www.asj.ad.jp/",
  "accountingPeriod": "【決算】3月",
  "establishmentDate": "【設立】1984.2",
  "listingDate": "【上場】2003.1",
  "feature": "【特色】サーバーホスティング業界中堅。ネット予約・決済、ブラウザ野球ゲーム等に進出。M&A注力",
  "business": "【連結事業】ネットサービス100 <16・3>",
  "assets": "",
  "finance": "",
  "nullColumn1": "",
  "comment1": "【買収効果】今年2月末のNTTデータERP子会社買収が通期寄与、年商10億円上乗せ。決済代行は柱の商議所向け簿記検定受付システムが終盤にかけ、積み上がる。のれん負担増や開発費増埋め、営業益増。",
  "comment2": "【取得】NTTデータERP子会社発行株の少数株主持分14・3%追加取得し、完全子会社化。同社製人事管理システムのクラウド対応急ぎ、本体とのシナジー追求。",
  "industryType": "【業種】 通信サービス 時価総額順位  87/97社",
  "vendor": "【仕入先】―",
  "customer": "【販売先】―",
  "rival": "【比較会社】3788 GMOクラ,4304 Eストアー,3633 GMOペパ",
  "headOffice": "【本社】332-0017埼玉県川口市栄町3-2-16 TEL048-259-5111",
  "branchOffice": "",
  "workerNumber": "【従業員】<16.6>連171名 単61名(35.5歳)[年]524万円",
  "security": "【証券】[上]東京(マ)[幹](主)SMBCフ(副)大和,日興,むさし,楽天,HS,松井[名]三菱U信[監]新日本",
  "bank": "【銀行】三井住友,埼玉りそな,武蔵野,三菱U",
  "affiliate": "【連結】イー・フュージョン,ASJコマース,アイテックス",
  "nullColumn2": "",
  "progress": "【四半期進捗率】3期平均7.9%* 今期-108%(-116%)",
  "holderNumber": "2496"
}
{
  "code": 7162,
  "creadtedDate": "作成日:2016年09月16日",
  "meigaraName": "7162 アストマックス  あすとまっくす  [証券・商品先物取引業]",
  "url": "【URL】 http://www.astmax.com/",
  "accountingPeriod": "【決算】3月",
  "establishmentDate": "【設立】2012.10",
  "listingDate": "【上場】2012.10",
  "feature": "【特色】商品先物の自己売買と商品投資顧問・投信委託が柱。大和証券GとマネックスGが大株主",
  "business": "【連結事業】アセット・マネジメント55(21)、ディーリング30(13)、再生可能エネルギー関連15(-66) <16・3>",
  "assets": "",
  "finance": "",
  "nullColumn1": "",
  "comment1": "【特配】投信・投資顧問は運用資産積み上げ効く。再生エネも熊本の大型発電施設7月売電開始、定額償却化が寄与。自己売買前期並みなら営業利益好転。非支配株主控除。子会社株売却益30%を3年間特配還元。",
  "comment2": "【売却】投信・投資顧問子会社株の33%超を10月ヤフーに売却。2~3年後メドに第2段階の売却で持分会社化。20年3月期自己資本60億円、ROE8%以上目指す。",
  "industryType": "【業種】 証券・先物 時価総額順位  42/51社",
  "vendor": "",
  "customer": "",
  "rival": "【比較会社】8739 スパクスG,8742 小林洋行",
  "headOffice": "【本社】141-0022東京都品川区東五反田2-10-2東五反田スクエア TEL03-5447-8400",
  "branchOffice": "【主要子会社】アストマックス投信投資顧問TEL03-5447-8411,アストマックス・トレーディングTEL03-5447-8435",
  "workerNumber": "【従業員】<16.6>連77名 単14名(45.3歳)[年]822万円",
  "security": "【証券】[上]JQ(S)[幹](主)大和(副)マネックス[名]みずほ信[監]トーマツ",
  "bank": "【銀行】りそな,みずほ,三井住友",
  "affiliate": "【連結】アストマックス投信投資顧問,アストマックス・トレーディング",
  "nullColumn2": "",
  "progress": "【四半期進捗率】3期平均13.7%* 今期―(―)",
  "holderNumber": "2493"
}
{
  "code": 9767,
  "creadtedDate": "作成日:2016年09月16日",
  "meigaraName": "9767 日建工学  にっけんこうがく  [サービス業]",
  "url": "【URL】 http://www.nikken-kogaku.co.jp/",
  "accountingPeriod": "【決算】3月",
  "establishmentDate": "【設立】1964.3",
  "listingDate": "【上場】1979.9",
  "feature": "【特色】技術開発型で多数の特許。景観・環境事業、消波ブロック、土木シートが3本柱。官公庁依存高い",
  "business": "【連結事業】型枠貸与14(-5)、資材・製品販売86(2) <16・3>",
  "assets": "",
  "finance": "",
  "nullColumn1": "",
  "comment1": "【反転増】震災復興関連の護岸ブロックが出荷ピーク続く。国の防災・減災計画も下支え。復興事業以外の型枠貸与もじわり復調。ただ協力会社の人手不足など隘路で、外注費が高止まり。営業益反発力いま一つ。",
  "comment2": "【ベトナム】駐在員事務所を17年4月現法化へ、ASEAN市場開拓に本腰。護岸ブロックのピークは後2年続く公算大。南海トラフ地震対策関連需要の取り込み狙う。",
  "industryType": "【業種】 建設関連製品・設備 時価総額順位  61/75社",
  "vendor": "【仕入先】―",
  "customer": "【販売先】―",
  "rival": "【比較会社】1813 不動テトラ,9764 技研興業",
  "headOffice": "【本社】160-0023東京都新宿区西新宿6-10-1日土地西新宿ビル TEL03-3344-6811",
  "branchOffice": "【営業所】北海道,東北,関東,北陸,中部,近畿中国,四国,九州,沖縄",
  "workerNumber": "【従業員】<16.3>連123名 単108名(48.8歳)[年]535万円",
  "security": "【証券】[上]東京(2)[幹]東海東京[名]三井住友信[監]太陽",
  "bank": "【銀行】三菱U,みずほ,三井住友,三井住友信",
  "affiliate": "【連結】東洋水研",
  "nullColumn2": "",
  "progress": "【四半期進捗率】3期平均-27.6% 今期-11.5%(+16.1%)",
  "holderNumber": "2489"
}

ここから、パイプをつないで、取得したい値だけをさらにフィルタリングで指定します。下記ではcodeとmeigaraNameという値を取得しています。

# curl -s -XPOST "http://localhost:9200/shikiho/shikiho/_search?pretty" -d @search_test_bk.json | jq -r ".hits.hits[]._source | [.code, .meigaraName]"
[
  2351,
  "2351 (株)ASJ  えいえすじぇい  [情報・通信業]"
]
[
  7162,
  "7162 アストマックス  あすとまっくす  [証券・商品先物取引業]"
]
[
  9767,
  "9767 日建工学  にっけんこうがく  [サービス業]"
]

さらにパイプで跨いで、csv出力するためのオプションを指定してあげると、csv形式で取得できるようになります。

]# curl -s -XPOST "http://localhost:9200/shikiho/shikiho/_search?pretty" -d @search_test_bk.json | jq -r ".hits.hits[]._source | [.code, .meigaraName] | @csv"
2351,"2351 (株)ASJ  えいえすじぇい  [情報・通信業]"
7162,"7162 アストマックス  あすとまっくす  [証券・商品先物取引業]"
9767,"9767 日建工学  にっけんこうがく  [サービス業]"

いろいろ便利です。